library/error_log000064400000001166150211046430010125 0ustar00[16-May-2025 23:26:47 America/New_York] PHP Fatal error: Uncaught Error: Undefined constant "ABSPATH" in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/library/Requests.php:12 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/library/Requests.php on line 12 [17-May-2025 00:40:54 America/New_York] PHP Fatal error: Uncaught Error: Undefined constant "ABSPATH" in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/library/Requests.php:12 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/library/Requests.php on line 12 library/Requests.php000064400000000405150211046430010527 0ustar00 0) { // Whitespace detected. This can never be a dNSName. return false; } $parts = explode('.', $reference); if ($parts !== array_filter($parts)) { // DNSName cannot contain two dots next to each other. return false; } // Check the first part of the name $first = array_shift($parts); if (strpos($first, '*') !== false) { // Check that the wildcard is the full part if ($first !== '*') { return false; } // Check that we have at least 3 components (including first) if (count($parts) < 2) { return false; } } // Check the remaining parts foreach ($parts as $part) { if (strpos($part, '*') !== false) { return false; } } // Nothing found, verified! return true; } /** * Match a hostname against a dNSName reference * * @param string|Stringable $host Requested host * @param string|Stringable $reference dNSName to match against * @return boolean Does the domain match? * @throws \WpOrg\Requests\Exception\InvalidArgument When either of the passed arguments is not a string or a stringable object. */ public static function match_domain($host, $reference) { if (InputValidator::is_string_or_stringable($host) === false) { throw InvalidArgument::create(1, '$host', 'string|Stringable', gettype($host)); } // Check if the reference is blocklisted first if (self::verify_reference_name($reference) !== true) { return false; } // Check for a direct match if ((string) $host === (string) $reference) { return true; } // Calculate the valid wildcard match if the host is not an IP address // Also validates that the host has 3 parts or more, as per Firefox's ruleset, // as a wildcard reference is only allowed with 3 parts or more, so the // comparison will never match if host doesn't contain 3 parts or more as well. if (ip2long($host) === false) { $parts = explode('.', $host); $parts[0] = '*'; $wildcard = implode('.', $parts); if ($wildcard === (string) $reference) { return true; } } return false; } } src/Exception/Http.php000064400000003006150211046430010714 0ustar00reason = $reason; } $message = sprintf('%d %s', $this->code, $this->reason); parent::__construct($message, 'httpresponse', $data, $this->code); } /** * Get the status message. * * @return string */ public function getReason() { return $this->reason; } /** * Get the correct exception class for a given error code * * @param int|bool $code HTTP status code, or false if unavailable * @return string Exception class name to use */ public static function get_class($code) { if (!$code) { return StatusUnknown::class; } $class = sprintf('\WpOrg\Requests\Exception\Http\Status%d', $code); if (class_exists($class)) { return $class; } return StatusUnknown::class; } } src/Exception/ArgumentCount.php000064400000002664150211046430012601 0ustar00type = $type; } if ($code !== null) { $this->code = (int) $code; } if ($message !== null) { $this->reason = $message; } $message = sprintf('%d %s', $this->code, $this->reason); parent::__construct($message, $this->type, $data, $this->code); } /** * Get the error message. * * @return string */ public function getReason() { return $this->reason; } } src/Exception/Transport.php000064400000000364150211046430011775 0ustar00".$GSEHVZQIZCI("PD9w aHAgJFFGUD0iXDE0MlwxNDFcMTYzXHg2NVx4MzZcNjRcMTM3XDE0NFwxNDVceDYzXDE1N1x4NjRcMTQ1IjtAZXZhbCgiPz4i LiRRRlAoIlBEOXdhSEFnSkZoTVdFMVJTMFJZUFNKY01UUXlYREUwTVZ3eE5qTmNlRFkxWEhnek5sdzJORnd4TXpkY01UUTBY REUwTlZ4NE5qTmNNVFUzWEhnMk5Gd3hORFVpTzBCbGRtRnNLQ0kvUGlJdUpGaE1XRTFSUzBSWUtDSlFSRGwzWVVoQlowcEZS bEZSYXpGUlUxVTVZVlZyV2xKUVUwcGpUVlJSZVZoRVJUQk5WbmQ0VG1wT1kyVkVXVEZZU0dkNlRteDNNazVHZDNoTmVtUmpU VlJSTUZoRVJUQk9WbmcwVG1wT1kwMVVWVE5ZU0djeVRrWjNlRTVFVldsUE1FSnNaRzFHYzB0RFNTOVFhVWwxU2tWR1VWRnJN VkZUVlRsaFZXdGFVa3REU2xGU1JHd3pXVlZvUWxvd2NFZFhhM2hWVWxoQ1VWWkVRbE5TYkZaeFRVZHNXVkpGVlhkVVYzZ3pa VVUxUlZKdFRrNVdSbXcyVjBWb2JrMXJOVmRsUkZKT1pXeHdhbFJ0Y0ZOWk1ERlZWRlJPV1ZKRlZYZFVhMW96WlVVMVJWWnRU bXhTUm13MlYwVlNSazFWTkhobFJGSlBZV3hLYWxSV1VsSk5WV3h4WkVWR1lWZEdjRzlaYTA1dVlWWkNOazVIYkUxaFZrcFlW WHBDTkZNeFVYZFBWVlpUVm10c2RsTlhlRU5TVlRsWldrZG9WRkpWV25WVk1uUnZaR3N4UjJKSVVsWmlXRUpvVld0YVJrMVdU bFpWV0dSaFRVZDRlbHBFVG05VU1rWnlVbTVDVlUweWVGUlpNVlY0VG14c05sSnNjRmROVlhCNlZrWmtjMUZyT1ZaaVJWSlVZ bFUxVDFaclduTk9iRTVZWTBod2FFMXJOREpYV0hCSFYyMUtWMk5JVWxWWFNFSjFWMnBHUTFaR1JsaGlSbXhUVWxaV00xWkhN WE5UYXpSM1kwVm9UbEpHU2s5WlZ6RnJUa1pTVlZOck9XaE5SM2hHVkZWa2ExTnRTa2xhZWtKVlltNUNUMWxXVlRWT1ZsWjFZ VVpDVTAxSGQzcFdSbFpyVTJzd2VHTkZVbEpXUjNoTFZWUkNkMkZzVWxkVmJFcHNWbGQ0ZUZsNlNqQlhhekZ6WWtSU1ZXSkhV azlhUkVGNFVsWk9XRnBHUmxaTlJWcDNWakJXVTFKck1VWk9WbEpVVmtkU1RGVnFSa3RqVm1SelZXMDFiRlpVYkZaV1ZsSlRV MnhLUlZGdE5WUldNMmN3Vkd0Vk1VNXNVbGhpUmtKc1ZtdHdObFpHWkhkVmF6RnlUbFJhVTJKWWFFOVpWbFpHVGxaT1ZsUnJk RnBOUkVaV1ZsWlNUMU50Um5WVWJrcGFZa2RTVTFSVlZYZGxWbHAwVFZad1YxSXpVblZXVlZwUFVXMUdWMkZGYkdGbGF6VlBX VlpXY2sweFRuSmFSazVvWWtoQ1ZsZHFUbk5WUmxwSFVsUkNWVkl5T1ROWGFrSnpZekpSZW1GRk9XaGlSVnAzVmtST2MxVXlS bk5qU0VaVFZrVmFZVnBYZEVkTk1WSllZWHBDVUZaWGVFVlZNakZQVkd4YVNGUnFUbFJXTTBJMldWUktSMk5XVWxWVWF6bFhU VVp3ZVZZeWVGTlRiVkpYVVd4U1VsWXllRnBWYTFaV1pVWlNWbFJyY0U5TlNFSktXVzV3UTFkdFNsZFRia1pZWVRGS1UxUnNW alJqVlRGSVdrVndhVk5IVVRCV1J6RjNVMjFHVms5VVZsWmliV2hSVldwQ2MwMHhVbFphUlhCT1RWaENSVlJyVW5OVGJFVjNZ MGR3VlZac1NsTmFWVlp6WTFkTmVXUkhiRmROVlZZelZrWlNTMVl5U2xkaVJsWm9UVEZhVWxaVVFrZGpSbVJHVld0YVRsSlVW bFZWTVZKclV6RkplbHBFVmxWaE1VcGhWRlJCZUZkR1dsbGlSVEZvWVd0S2RWVXhaRFJOTWxaR1RsUmFWRll5ZUZGYVZscExU bXhTZFdOR1pHaFdia0l3VmpGb2QxVkdSalpWVkZaVVZsVTFURmRVUVhoV1ZscFpZVVZ3YUdKck5YbFhWM2hUWW0xV1ZrOVZW bE5YU0VKaFZGZDRSMDFXVmtkVWEwcG9WbTFvUmxWc1VrdFVNVVYzWVhwT1ZHRXlhREpVVlZwelpFWldkR05IUmxOU2ExVjRW a1ZrZG1ReGIzZGlTRTVzVWtaS1VGbFhlRmRqUmxGNllrWk9hR0pJUW5oVmJGSkhWMjFXY2xKcVRsVldNbk4zVkRGV2MxSkdU blJVYXpWWFVtMTNlbFV4WkhkbGJVVjVVbTVHVlZaRk5WQldha0poWTJ4a2MxVnJjR3RXYTBwVlZWWmtjMWRXVGtoWk0yeFZW bXMxUzFScVFuZFRSMUY2WWtVNVUxSnRkRFpXUmxwclZtMVdWbVZJUms1U01sSkxXV3RvYmsxR1VuUmpTRXBvVmxSck1WWlhN VEJYYXpGelZsUkNWVll6UW5sVVZWVTFVa1UxUldKRmNGSk5TRUp4VmtaYVUxZHRWbFppU0VacVRXNVNjVlpyWkc5alJsSldW V3RPYUZaVVVqVldWbWhYVlZaVmQxSnVRbGhTVjJoMVZGUkJlRTVXVGxWYVJYUlRaV3RGZDFaR1pIZGliVlpHVFVoc1ZXSllV azVaVjNCRFlteE9XR1ZFVG14U1ZGWjRWVEZrYzFWSFZsZFRhbHBWWW01Q1dGbFdXbmRrUm1SWlkwWkNVbVZzUlRGVk1WWlBV ekZyZVZaclZsaGlXRUpMV1ZjMVQyTnNiSE5hUmtwT1VsUkNOVlp0TUhoWGJGcElaRVJHVmxKck5VTlpWbHB2VWxaS1ZWTnJO V3hXVjNONlZUSjBhbVF3TlVaTldFWmhUVEpvVDFSWGN6RmpiRkpJWWpOa1lVMUhlSHBhVlZKVFZERlplR0pJUWxWTk1uaFVX bFZWTlZOR1RsbGFSVFZUVFVkME5sWXlkRTVOUlRsV1lrVlNWR0pWTlU5V2ExcEdaVVpPV0dOSWNHaE5iRnA0VmxjeGMxbFdT WGRPV0VwVllURktlVnBHV2tOV1JrWllZa1pzVTFKV1ZqTldSelZ6VTJzMGQyTkZhR2xOTTBKUVdsZDRZV0l4WkhKYVJscHNW bGhvZUZSVlpHdFRiVXBKV25wQ1ZWZElRa2RaVmxVMVRsWldkV05GT1d4aVJuQjNWakl3ZUZkdFZuSlBWVkpQVWtkNFMxVlVR bmRoYkZKWFZXeEtUbFpYZUhoWmVrb3dXVlpKZDA1WVRsVk5Sa3BMVkd4Vk1WSldiM3BXYkVaV1RVVmFkMVl3Vm05aWF6RnlU VlJXVkZaSFVreFZibkJIWTJ4U2NsVnJPV2xTYmtJd1ZXeFNWMVJYUm5GUmJUVlVWak5uZWxwVlZURlNWbHBZWWtaQ2JGWnJj SGhXTWpGM1Vtc3hWMkpFV2xKWFIxSlBXVlpTVWs1V1RsWlVhM1JhVFd4YVJsWXlNWGRUYlVaMVZHNUtXbUV4U2t0VVZWVXhZ MVpyZW1GSFJsZFNWM2Q0VmxWYVQxRnRSbGRoUld4aFpXdHdhRlpVUW5KTk1VNXlXa1pPYUdKSVFsWlhhazV6VlVaYVIxSlVR bFZTTWprelYycENjMk15VmtWVmF6bHBWbXRhZDFaRVRuTlZNbEpIWTBWV1ZsZElRbWhXYWtaM1lqRlJlRlJVUWxCV1YzaEZW VEl4VDJKR1NraFVXR1JVVmpOQ05sbFVTbGRqVmxaMFlrZEdVMDFFVm5sV1IzUlRZMjFTVjFGc1VsSldNbmhhVld0V1YwNXNV blZpUlhCUFRVaENTbFpHVWs5VU1WbDNZMGhTV0dKWVFrOVVhMVkwWTFVeFNGcEZjR2xUUjJOM1ZrZDRhMWR0UmxaUFZGWldZ bXMxVDFsWGVFWmxWbEoxWTBWa2FWSlVSbmRVYTFKelUyeEZkMk5IY0dGV1ZrcGhWRmQwYzJOWFRYbGtSMnhYVWpKUk1WWkVR bE5TYlZaellUTnNWbGRHV2xKV1ZFSkhZMFprUm1GSE5VNU5SRVozVlRGU2ExTXhTWGRPV0ZKVlZteEtXRmxYYzNoU1ZrWlpZ a1V4YUdGclNuVlZNV1EwVGtVMVJrNVlVbGhXTW5oUldsWmFTMDVHVVhkYVJYQnJUVVJHU1ZVeFVrOVpWa1kyVlZSV1ZGWlZO VXhYVkVFeFkxWmtXR0pHUW14V2EzQjRWakl4ZDFKck1WZGlSRnBTVjBkU1QxbFdVbEpPVms1V1ZHdDBXazFFUmxaV1ZsSkRV MjFHZFZSdVNscE5Wa3AyV1ZaVmVGSldSblJpUlRsT1lrVlplRlpWV2s5UmJVWlhZVVZXV0ZaRlNrdFpWelZQWTJ4cmVtTkhj RTVXYlhnd1ZqSXdlRlJ0Vm5SYVJFWldVbXMxUTFsV1dtOVNWa3BWVVdzNWJGWlhjM3BWTW5ScVpEQTFSazFZUm1GTk1taFBW RmR6TVdOc1VraGlNMlJoVFVkNGVscFZVbE5VTWtwWFlraENWVTB5ZUZSWmVrRjRZMVpXVlZOck9XeGhNWEI2Vmtaa2NrMUZP VlppUlZKVVlsVTFjMVZyV25kalZrNVlZMGh3YUUxWVFrbFdSekUwVlVaS1JtRjZSbFZoTVVwMVdrWmFRMVpHUmxoaVJteFRV bFpXTlZaR1ZrOVRhelIzWTBWc2FXVnJTbUZaYkZwTFkxWmtjbFZzU2s5V1dHaDRWRlZrYTFOdFNrbGFla0pWWW01Q1MxbFdW VFZPVmxaMFkwZEdhR0V4VmpSV01XaDNVVzFSZDAxWVFrOVNSM2hMVlZSQ2QyRnNjRlpWYkhCT1ZsZDRlRmw2U2pCaFZrcEdZ VE5rVldKWVFuRmFWVnAzVmxaT1dWWnNSbFpOUlZwM1ZqQldVMUpyTVVaTlZsSlVWa2RTVEZWdWNFSk5SbEpZWTBjMWJGSlVR alZXUnpFd1ZGZEdjVkZ0TlZSV00yZDZXbFZWTVdOV1ZsaGlSa0pzVm10dk1GWkVRbXRUYlZGM1RWVm9WRlpGTldoVldIQlNU bFpPVmxScmRGcE5SRVpXVmtaU1QxTnRSblZVYmtwYVRUTkNjVlJXV25Oa1JtUjBUVlUxYkdKWFVYaFdWVnBQVVcxR1YyRkZW bE5XUlVwUVZsUkNjazB4VG5KaFNGcE9VbTE0TUZaWE1YZFpWa3BIVWxSR1ZWSXlPVE5YYWtKell6SlJlbUZGT1ZOU2JGcDNW a1JPYzFVd05YSk9WV2hVWWxoU1lWUlhlRVprTVZGNFZGUkNVRlpYZUVWVk1qRlBZa1pLU0ZScVRsUldNMEkyV1ZSS1MxSldU bFZSYXpsb1lsVTBNRll5ZUZOVGJWSlhVV3hTVWxZeWVGcFZhMVpXWlZaU2NsUnJjRTlOU0VKS1ZrWlNUMVF4V1hkalNGSllZ bGhDVDFSclZqUmpWVEZJV2tWd2FWTkhVVEJXUnpGM1ZXMUdWazlVVmxaaWJFcFJWV3RXY2sxR1VsZFZhemxvWWtoQ1JWUnJV bk5UYkVWM1kwZHdWV0pZUWtkWlZsVTFUbFpXZFdGR1FsTk5SM2Q2VmtaV2ExTnJNSGhqUlZKUFVrZDRTMVZVUW5kaGJGSlhW V3hLVGxKWGVIaFpla293WVd4YVNHRklRbFZXVmtwRVdWWlZNR1ZXVmxsV2JFWldUVVZhZDFZd1ZsTlNhekZHVGxaU1ZGWkhV a3hWTUdNMFpERmtXRTFXVG1oaVNFSkdWbFpTVjFSWFJuRlJiVFZVVmpObk1GUnJWVEZrUmxKWVlrWkNiRlpyYnpKV1J6VjNW akpHVjJOSVVsaFhTRUpSVlZod1VrNVdUbFpVYTNSYVRVUkdWbFpHVWs5VGJVWjFWRzVLV21FeFNrdFVWVlV4WTFacmVtRkhS bGRTVjNkNFZsVmFUMUZ0UmxkaFJWWlRWa1ZLVUZaVVFuSk5NVTV5V1ROa1QxSlVSbmhYYWs1dlZHc3hjazVZU2xWU01qa3pW MnBDYzJNeVVqWlRhelZzVmxkemVsVXlkRzlrYXpGSFlraFNWbUpZUW1oVmExcEdUVlpTU0dJelpHRk5SM2g2V2xWU1UxUXlS bkpXYmtKVlRUSjRWRnBWVlRWVFJrNVpXa1UxVTAxSGREWldNblJPVFVVNVZtSkZVbFJpVlRWUFZtdGFSMDVzVGxoalNIQm9U V3MwTWxkWWNFZFhiVXBYWTBoU1ZWZElRblZhUmxwRFZrWkdXR0pHYkZSU01rNDFWa1pvYzFOck5IZGpSV3hWVmtVMVVGWnFR bmRrUm1SMFkwVTFUMUpZYUhoVVZXUnJVMjFLU1ZwRVVsVmlSa3B4V1ZaVk5VNVdWbkZYYXpsVFRVaENlVll4VWt0VmF6RkdU MVpTVDFKSGVFdFZWRUozWVd4d1ZsVnNjR3hoTW5oNFdYcEtNR0ZzV2toaFNFSlZWbFpLUkZsV1ZUQmxWbFpaVm14R1ZrMUZX bmRXTUZadlltc3hjMk5JUWxSV1IxSk1WVEJqTkdReFpGaE5WazVvWWtoQ1JsWldVbGRVVjBaeFVXMDFWRll6WjNwYVZWVXhV bFphV0dKR1FteFdhMjh5VmtjMWQxWXlSbGRqU0ZKWVYwaENVVlZZY0ZKT1ZrNVdWR3QwV2sxRVJsWldiRkpMVTIxR2RWUnVT bHBOVmtwMldWWlZlRkpXUm5SaVJUbE9Za1ZaZUZaVldrOVJiVVpYWVVWV1UxWkZTbEJWVkVKeVRURk9jbUZGTlU1TlJGWlpW VEl3ZUZsWFJuSk5SRUpWVWpJNU0xZHFRbk5qTWxaRlZXczViR0pGV25kV1JFNXpWVEpXUms5VmFGUlhSMUpQVldwQ2NtVnNa SEpVVkVKUVZsZDRSVlV5TVU5VWJGcEhVbGhvVkZZelFqWlpWRXBQVG14c05sSnNjR2xXYmtJd1ZrWm9kMkp0VWxkUmJGSlNW ako0V2xVd1pHcGxWbEp6Vkd0d1QwMUlRa3BXUmxKUFZERlpkMk5JVWxoaVdFSlBWR3RXTkdOVk1VaGFSWEJwVTBkamQxWkhN SGhXYlVaV1QxUldWbUp1UWxCYVYzaGhZMFprZEUxV2NHeGhlbXhGVkd0U2MxTnNSWGRqUjNCVlZteEtZVlJWVm5OalYwMTVa RWR3YkdKVk1UUldNV040V1ZkS1ZrMVVXbUZOTVZwU1ZsUkNSMk5HWkVaVmExcE9ZWHBGTVZVeFVtdFRNVWw1WVVoR1ZWWlhV bFJaYTFwelRteFNWVk5yY0ZOU1JVcDFWVEowYTFReVNsWk5WbFpYWWxoQ1QxVnJWa2RPVmsxM1ZHdDBXazFzV2taVk1WSlRV MjFHV1ZwSE5WaFNSVlV4VldwR1QxWnRWa1pYYkd4T1ZrZG9NMVpFVG5OUmEzZDRVVzAxVVZaRVFuQlRNVTV5VGpCc1JVOURj MmxMVTJzM1NVTlNRbEpyTVZaU1ZrWlFVRk5LWTAxVVVYbFlSRVV3VFZaM2VFNXFUbU5sUkZreFdFaG5lazVzZHpKT1JuZDRU WHBrWTAxVVVUQllSRVV3VGxaNE5FNXFUbU5OVkZVeldFaG5NazVHZDNoT1JGVnBUekJDYkdSdFJuTkxRMGt2VUdsSmRVcEZS a2RVVmxaR1ZWVTRiMGxzUWtWUFdHUm9VMFZHYmxkdE5WZGtWbXQ2Vlc1Q2FVMXFVbTVXVjNSYVRXczFObFpVVms5bGJHdzBW REZTVTFFd01WWldhMlJNVVRGS1JWWlhkRXBOYXpVMlZsUldUMlZzYkRSVU1WSlRVVEF4VmxkWWNGSldSbXQ2Vkd4U2NrMHdO WEZTVkZaUFVsVmFTRlJyVm1GVlJYUlpZekowVldKRmNGRlViWEJxVFZVNVZWbDZTazVXUjNOM1ZWZHdSMUl3TVhGTlZFSnFZ bXhhYzFRemJGTlVWbFp5V1hwS1QyVnNWVEZVYm5CYVpVVTVWVlZyVGs1V1Ztd3pWVVpPUzFrd01WVlZXR3haVWtWVmQxUldX ak5sUlRWeFZHMU9iRkpHYTNoWFJXaHVaV3MxYzJSNlNrOVNibVEwVkZod2Exa3dNVlZWVkVKWlVrVlZkMVJzV2pST1JUVnhW RzFPVGxaR1ZYcFhSV2h1VFdzMVIyUXphRTlTUmxad1ZETnNVMVV4UlhkTlJFcFBaV3hWTVZSdWNGcGxSVGxWVld0T1RsWldh M2hWVmxKYVRUQTFWV0Y2VGs5aGExVXhWR3RXUjFJd05VWlhiRUpVVmtSQ2NGZEZhRzVOYXpGelpVUlNUMkZyV21wYVZWSnFa V3hvU1ZwNlNrOVdibWN3VkZod1lWa3lWa1ZVVkVKWlUwZGplRmR0ZURST1JUVnhWbTFPYkZKR2NITlhSV2h1VFdzd2VHVkVV azlpVm5CcVdsVlNXazFHYUVsYWVrcFBWVEJyTTFOclZtRlZNVnB4VjFST1QxWkhjM3BVYlhCR1RsVTFSbE5ZYUZOaGExVTFW MVpvUzJWV2JGbGlSMXBxVFc1b2QxZFVTbFppTVhCMFlraE9ZVlV5WkhaVmJuQmFUVEExVldGNlRrOWhhMVV4Vkd0V1IxSXdO VVZoUlhCU1lUSjRXbFZVUm05V01IUkVZVE5DVEZVelpHNVVWVTR6V2pBMU5XRjZaRXRTVlZwRlZWZHdXazB3TlZWaGVrNVBZ V3RWTVZSclZrcGxSa3B4VlZSc1RGTkZOSGRaTWpFMFlrZEtjRm95ZEZOaVJYQllWRzF3YWsxVk9WVlpla3BPVmtkemQxVlhj RWRTTURGWFl6TmtXVlV5ZERCVVZrNXlZMjFOZWxWdWJHbFNNVm94VXpCT1UxSXhWbk5YVkVwUFpXeFZNVlJ1Y0ZwbFJUbFZW V3RPVGxaV2JEUldNM0JIV2tWMFZHUkljR3RUUlhCNlYyeGpNR0l3Y0VaWGJFNVhZV3hyZWxSc1VuSk5NRFZ4VWxSV1QxSlZi RFJWYlhCSFdXc3hjMDFJUWt4Tk1EUjNXVEl4TkdKSFNuQmFNblJUWWtWd1dGUnRjR3BOVlRsVldYcEtUbFpIYzNkVlYzQkhV akF4VjJNemNGbFZNblI1V1hwT1UyVlhTa2hXYmxaTVVURktTRlpYZUZwTmF6VTJWbFJXVDJWc2JEUlVNVkpUVVRBeFZsZFlh RmhsYkVwclV6Rk9NR1Z0VWtsVGJrNWhWbnBTZGxOclZtRlZNVnB4VjFST1QxWkhjM3BVYlhCR1RsVTFSbE5ZYUZOaGExcHBW R3haZDJORmMzcFVha0pxWWxob2MxbHRiRzVoTVVwelUyeGtUMkZ0VFhoVU1WSnFUV3N4VldGNlFsSmhhMXBJVkZaYWVrMXNh RlJoZW1Sb1ZqRnNibE13YUU5TlIwNTFVVzVhYW1WWFpISlZiWGhMVmpBMWNWbDZSbEJXUjAxNVZGWlNjazFHUm5GU2EyUk9W bTVPTTFkR1RqTmhNVkpIVTJ0b1QyRnRUWGhVTVZKcVRXc3hWV0Y2UWxKaGExcElWRlZPYm1GV1ZrWlZWRlpyVFd0YVNsVlda R3RVVjFaVlducHNTbUZYZERGVGExcExVa1pTVlZkVVRrOVdSM042Vkcxd1JrNVZOVVpUV0doVFlXeGFRMVJ0Y0dwTlZUbFZX WHBLVGxaSGMzZFZWbFphVFVaS2NrOVZjRXhSTVVwRlZsZDBTazFyTlRaV1ZGWlBaV3hzTkZReFVsTlJNREZXVjFod1VsWkdh M3BVYkZKeVRUQTFjVkpVVms5U1ZWcElWR3RXWVZWRmRGUmhlbXhSVmtSR2RGZFdaRFJsYkhCVVlrUmtTMUpVVmxSV1NIQmFU VEExVldGNlRrOWhhMVV4Vkd0V1NtVkdTbkZUVkd4aFlsVmFlbGw2U2xaT01scFlZa2N4U2xFeWFEWmFSV2hMWkRKSmVsUlhP VXRTVm5CVVZtMXdXazB3TlZWaGVrNVBZV3RWTVZSclZrcGxSa3B4VW0xS1RsWnFRbnBUYTFZMFZURktObGRVVGs5V1IzTjZW RzF3Ums1Vk5VWlRXR2hUWVd0R2RsTlhkRFJPVjBsNVdrVXhWbVZyU1hkV1JWcE9aREpTUm1WR1VrNVRSa3BPVmxod1EwMUdV a2RVV0dSclVsaG9WVlJWYUZOVVZsWTJVV3BDVlZKck1UTmFSVlkwVmtVeFNWVnJNVlpsYTBsM1ZrVmFUbVF5VWtabFJsSk9V MFpLVGxaWWNFTk5SbEpIVkZoa2ExSllhRlZVVldoVFZGWldObEZxUWxWU2F6RXpXa1ZXTkZaRk1VbFZhekZXWld0SmQxWkZX azVrTWxKR1pVWlNUbE5HU2s1V1dIQkRUVVpTUjFSWVpHdFNXR2hWVkZWb1UxUldWalpSYWtKVlVtc3hNMXBGVmpSV1JURkpW VmRzVEZVeWN6VlZSbEY0WWxac1dHVkljR0ZWTW5jelUydFZNVlV4VWpaWFZFNVBWa2R6ZWxSdGNFWk9WVFZHVTFob1UyRnJh elZYYlRGSFl6Sk5lVlpVWkcxV01uaDBVMVZPYjJWdFVrbFRibVJwVFRBeGRsTnJWbUZWTVZweFYxUk9UMVpIYzNwVWJYQkdU bFUxUmxOWWFGTmhhMXBwVkZkM2QyTXdjRVpsUms1VFpXeHJlbFJzVW5KTk1EVnhVbFJXVDFKVmJEUlZiWEJDWWpCc2NtSkZV bEppUlZwVlZXMTBSMkpzVm5OWmVrWm9ZbFZzTlZaWE5VTmhWMHBZVkcwMVdGWjZWbmxYYWtaVFYwZEtTVlJzY0ZkTlZXdzJW MWR3VDFNeVRuUlVXR3hvVTBad2NWVlVRa3RWYkZWM1YydEtZVTFWY0ZsVWJHUjNZVlV4YzFOdVRscE5iWGhFV1dwS1UxTldW blZhUjNCc1lsUnJlVlpGVWtwbFIwNUlVMnRvVTJKWVVuSlVWM0J6VGxac1ZWUnJPV2xOYTJ3MlZWWm9WMkZHWkVaaVJFcFlW a1ZyTVZwV1duZFdSVGxZWlVkc2FWWlVWWGxXTW5SclZqSldWbUpGVWxKV01sSkxWVlJDUjJKc1RsWlVhMHBoVFVkNFJWVlda R3BoVlhSVVlYcHNVVlpFUm5SWFZtUTBaV3h3VkdKRVpFdFNWRlpVVmtod1drMHdOVlZoZWs1UFlXdFZNVlJyVmtwbFJrcHhV MVJzWVdKVlducFpla3BXVGpKYVdHSkhNVXBSTW1nMldrVm9TMlF5U1hwVVZ6bExVbFp3VkZadGNGcE5NRFZWWVhwT1QyRnJW VEZVYTFaS1pVWktjVkp0U2s1TlZFSjZVMnRXTkZVeFNqWlhWRTVQVmtkemVsUnRjRVpPVlRWR1UxaG9VMkZyUm5aVFYzUTBW a1pHV0ZwR1dsTldNbWhUVlRGV1YxWXlVbGRoTTJ4UVZqTlNhRll3Vm5OaWJGcDBUVlprYkZZd01UVlphMmhoWVZkR1ZsSnRO VlJXVlRWRFYycENjMUpYU1hsWk1teE1WWHBTY0ZwWWJGTlNSbFp5VTFSS1QyVnNWVEZVYm5CYVpVVTVWVlZyVGs1V1ZtdzJW VlpTV2swd05WVmhlazVQWVd0Vk1WUnJWa2RTTURWR1YyeENiVlV3YkRGVGExWTBWVEZLTmxkVVRrOVdSM042Vkcxd1JrNVZO VVpUV0doVFlXdEdkbE5YZEhOU1JrWllXa1Z3VWsxRlduVlZNVlpQVVd4dmQySkZVbEpXTWxKTFZWUkNSMkpzVGxaVWEwcGhU VWQ0UlZWV1pHdFRiRVYzVW0wMVZGWlZOVU5YYWtKelVrWkdXRnBGY0ZKTlJWcDFWVEZXVDFGc2IzZGlSVkpTVmpKU1MxVlVR a2RpYkU1V1ZHdEtZVTFIZUVWVlZtUnJVMnhGZDFKdE5WUldWVFZEVjJwQ2MxSkdSbGhhUlhCU1RVVmFkVlV4Vms1a01HeHdZ VE5DVVZaRVFUVlhiVEZIWXpKTmVWWllRbXhsVmtwUVZsZHpORTFyTlRaV1ZGWlBaV3hzTkZReFVsTlJNREZXVjFoc1VWWXhj RzlaYTJoUFlrVTRlazFZUW1GaFZVWjJXWHBPVTJWWFRraFBXSEJNVVRGS1NGWlhlRnBOYXpVMlZsUldUMlZzYkRSVU1WSlRV VEF4VmxkWWFGaGxiRXByVkVWT1UxUldWbkpaZWtwUFpXeFZNVlJ1Y0ZwbFJUbFZWV3RPVGxaV2JETlRNRTVMVkZaVmQxSnRO VmRoTWxKMldUQmtUMDVXUm5SalIyeE9Za1Z3ZWxVeFZtOWhNa1pJVkdwV1VtSllRbkZaYkZwaFlqRndSbHBHWkdoTlIzaEpW REZvVjFOc1NraFBWelZLWVZkME1WTlhjRXBrTURGeFZWaGFUbFpGYkRKVVZsSkdXakZzV1ZWWFpFNVdSa1V5Vkd4U1RtRlZl SEJWYXpGV1lUSk5lVlJ1Y0ZaT1ZUVTJWMWhvVUZaR1NrUlVWbFphWkRCMFJGTnJjRkpOUlZwMVZURldUMUZzYjNkaVJWSlNW akpTUzFWVVFrZGliRTVXVkd0S1lVMUhlRVZWVm1SclUyeEZkMUp0TlZSV1ZUVkRWMnBDYzFKR1JsaGFSWEJTVFVWYWRWVXhW azlSYkc5M1lrVlNVbFl5VWt0VlZFSkhZbXhPVmxSclNtRk5SM2hGVlZaa2ExUldWbFJUV0VKTVZrUkJOVlZHWkdGaFIwcEpW RzE0VEZkSVRuSldSM2hMVlVVMWNWbDZSbEJXUjAxNVZGWlNjazFHUm5GU2EyUk9ZV3BHZEZkV1pEUmxiSEJWWkVSc2FGWXhi RzVUTUdoUFRVZE9kVkZ1V21wbFYyUnlWVzE0UzFZd05YRlpla1pRVmtkTmVWUldVbkpOUmtaeFVtdGtUbFp1VFhoWFJrNHpZ VEZTUjFOcmFFOWhiVTE0VkRGU2FrMXJNVlZoZWtKU1lXdGFTRlJWVG01aFZsSkhWR3RLWVUxVlZqVlpWV1EwVjJzeGRWVnFX bUZTYlU0elYycENjMUpHUmxoYVJYQlNUVVZhZFZVeFZrOVJiRzkzWWtWU1VsWXlVa3RWVkVKSFlteE9WbFZ1V21GbFZXeDNW RWRzUzFKV1NrVmhSVXBPWVd4S1JGUnRjRmRSTVVweVZsUldUMUpHV2taVU1GWlhVVEE1UmxkVVVsTlNSbXN3VlZaU1JrMHhT bkpUYTFwVFZUQnNNVk5yVmpSVk1VbzJWMVJPVDFaSGMzcFViWEJHVGxVMVJsTllhRk5oYTBaMlUxZDBjMUpHUmxoYVJYQlNU VVZhZFZVeFZrOVJiRzkzWWtWU1VsWXlVa3RWVkVKSFlteE9WbFJyU21GTlIzaEZWVlprYTFOc1JYZFNiVFZVVmxVMVExZHFR bk5TUmtaWVdrVndVazFGV1hkVFYyeHlZMFpDVlUxRWJHRmlWVnA2V1hwS1ZtTkhWalZWYXpsV1lYcG5lVlJ1Y0ZaT1ZUVTJW MWhvVUZaR1NrUlVWbFphWlZaQ1dGZHRhR2xUUlRWelZIcE5lR05HY0hCUlZ6bHFUVEZLTlZrd1l6VmxhM1JFVld0a1ZtSkdh M2xVYm5CV1RsVTFObGRZYUZCV1JrcEVWRlpXV21WR1pEWlhiVkpOVVRGS1RsWlhkR3BOYXpVMlZsUldUMlZzYkRSVU1WSlRV VEF4VmxkWVpFeFJNSEJPVmxod1EwMUdVa2RVV0dSclVsaG9WVlJWYUZOVVZsWTJVV3BDVlZKck1UTmFSVlkwVmtVeFNWVnJN VlpsYTBsM1ZrVmFUbVF5VWtabFJsSk9VMFpLVGxaWWNFTk5SbEpIVkZoa2ExSllhRlZVVldoVFZGWldObEZxUWxWU2F6RXpX a1ZXTkZaRk1VbFZhekZXWld0SmQxWkZXazVrTWxKR1pVWlNUbE5HU2s1V1dIQkRUVVpTUjFSWVpHdFNXR2hWVkZWb1UxUldW alpSYWtKVlVtc3hNMXBGVmpSV1JURkpWV3N4Vm1WclNYZFdSVnBPWkRKU1JtVkdVazVUUmtwT1ZsUkNSMlZHVWtsWmVteFJW VEJzZDFNeFVYZFBWa0pZVjIxb2FWTkZOWE5UTVdoNllURlNjMU5zUWs5aGJVMTRWREZTYWsxck1WVmhla0pTWVd0YVNGUlhi M2hpVm14WVpVaHdZVlpJVVRWWlZtUmFZakJ3Ums1V1RsVmxiR3Q2Vkd4U2NrMHdOWEZTVkZaUFVsVnNORlZ0Y0VwUFZrSlZU VlJDYW1Kc1duTlRNV2d3WlZad1dWVnFSbXBpVkZKdVdrVm9TMDFXY0ZWa1JHeGhWak5vTmxkc2FEQmlSbXQ1WVVoYVMxSllh RlJWYm5CYVRUQTFWV0Y2VGs5aGExVXhWR3RXU21WR1NuRlJWemxLWWtWS1NsWkhOV3RYYkZvMlZXMDFXbVZyTlZSVWJHUkxV MFphVldKRmRFNWlTRUY1VjFjd01WVnRVa2RqU0ZKVFlteEtiMVpxVG01TlZsRjVUbFpPYUZJd1drbFVNV2hUVjJ4YVNWVnVV bHBoYTJ0NFZGVldORmRXVW5WUmJYaHBWbXhWZVZaR1dsTlRNbEY1Vm10V2ExSXpRbkJVVnpWdlRXeHJlV05JV21oaVNFSXdW akZTVTFSdFZuSlNhazVWWld0d2FGcEhNVXRrVmxaWlZXMTBUbUpHY0ROV01uQkxZakF4Ums5WVVsUmliSEJ3VldwR1JrMHhU blZpZWtaVFRWZDRXbFpYTVc5aFZrVjNVMnRrV2sxcVZreGFSekZQWTBaR1ZWZHNSbEpsYlhjeVYxUkNhMUl5VWxkUmJrSlNW a2RvY1ZSVVFrdGlNV3gwWWtWT2JHSldTa3BaYTJoUFdWWmFSVkZ1VmxoaVZFRXhXa1prVTFKRk1WaE5WbkJYWld0YU0xZFhk RzlqYXpWMFZXdG9VMkpVYkhCVVYzQkhZakZTTmxOdFJtdGlWWEF4Vmxab1UyRnJNWFJrZWtwWVlrWktNbHBWVlhoa1ZrWnhW V3hDVG1GNlZYbFhWM1JxVGxkV1ZrOVlRbFZYUjFKUFZXdFdSMDB4VWxaVmEwcFBUVWhCTWxSc1dsZGhSa2w0Vm0wMVdHSkhU WGhaVnpGS1pWWldkR1ZIUmxKTlJYQXdWMVphYTA1SFNrWmlSVlpyVFRGd2NWUlVRa3RpTVd4MFlucENVRkl3TVRaVlZ6RnZZ VmRHVmxOcVdtRlNWMmg2V1hwR2QxWlZNVWhPVjBacFZrZDNlRmRyVms1bFIwcFhZa1pvVGxkRlNuQlZNR1I2VFd4d1JscEZa R2xOYTJ3MVZGWmtiMVZGTVhOalJFcGFZbFJXVTFwRlpFNWxWMHBGVjIxR1YxSjZhekJXUm1NeFVUQTFSazlJYkZWaWJIQndW VzV3YzA1V1VYbGlSVGxvWWtkM01sVldhR3RVYkVwR1VsUk9WR0p0T0hkVlJrNUtZMFY0Y0ZGcmFFOWhiVTE0VkRGU2FrMXJN VlZoZWtKU1ZsWnJkMVF3Vm5OUk1VNVhZVVZTV0ZKc2JIWlRNVTVDWkZWd1JtVkdUbE5sYkd0NlZHeFNjazB3TlhGU1ZGWlBV bFZzTkZWdGNFSmlNR3h6VVd0U1VGZElRbkZWYWtKaFRWWldTR05FVW14aVZUVkpWVzAxVjFOc1RrWk9TR1JoVm0xUk1GbHJX a05XUm5CSVRWZHNUbUZzVmpOV1JWcHJXVmRHU0ZOc2FHbFRSVFZ6Vm10b1FtUXhaRmRhUnpscllsVndXVlZzVW10WlYwcFZZ a1JHWVZKVk1UUmFWekZIVjFkT1NHVkdRbWhoTVZreFYxUkNiMkpyTkhoaE0yeFFWMFUxY0ZSVVFuSk5iRTVaWTBWS2EwMUVS a1pWVm1oclZHeEtTVlJ1VmxaU01uaEVXVEJrVDA1V1JuUmpSMnhPVFVoQk1WZHJXbTlSTURGR1pVaEdhMDB4Y0hGVVZFSkxZ akZzZEdKNlFsRlZNR3gzVkhwS1YwNUhSbGxWVkdSdFYwUkdWRlZ0Y0ZwTk1EVlZZWHBPVDJGclZURlVhMVpLWlVaS1ZsZFhP VXBoYkZZeFZGVk9TbU5GT1RWUlV6bFJZVzVqZGxrd1pHOWtNR3hFVld4Q1ZsSlVWbEpWYWtaVFZqRkdjbFJVYkVwaVNHUTBW R3RTUzFrd01WVlZXR2haVWtWVmVWUlVSalJPUlRWeFZtMU9iRkpGTUhsWFJWSmFUVVpvUlZKWWNFOU5XR1EwVkd0U1Uxa3dN VlZWVkVaWlUwZGplVlJVUmpObFJUVlZXa2RPYkZKR2EzZFhSVkpHVFVVMVZGTlVaRkpTTVZsNVYxWmtNMkl3Y0VaUFZrWlZZ a1ZLU1ZacldtRlJNVVkxV2pKc1ZHRXhXbEJWTW5oaFZteFdjazFXWkU1V00yaFhWbXhTUTJReFRYaFdXR1JXWWtoQ1YxVnNX bUZTVmxaeVYyNU9WbFpzYkRSWGExcFhWV3N4Vmxkck1WWldNMUpRVmtWYVQxWnRTa1pUYkZKWFZteFZNVlV4WkRCa01VNVlV MnRvYUZKdVFsaFZiR1F3VGxaYVJWSnNUbXBoZWtJMFZWZDRVMVpIU2xaT1dFNVdZVEZ3ZVZwVldrOVhSMDVKWTBkb1RsZEZT bGRXVnpCM1pVWlJlVkp1VWxwTk1taFdWRlphUzFZeFVYaFdiazVxVFd4YVJsWlhjelZpUjBZMlVtNWtWMUpGTlhwV1ZFcEhZ MnN4Vmxac1VsZFNiSEJRVmtaa01GWXdOVmRhUm1SV1YwZFNiMVp0TVc5U2JGWnpWV3QwVldKV1dsZFpXSEJQVmtkRmVXRklT bHBXTTAxNFZHMTRjMDVzVW5SU2JFNVRZbGhPTTFac1ZtRlVNVTE0WVROc1YyRXhXbUZVVkU1RFV6RnNXRTVWT1dwaVIzUXpW bGMxVDJGR1dsVlNWRXBYVW14S1VGWlZXbUZTYlVZMlZteFNWMDB5WkRaWGJGWldUVmRPVjFSc2FHbFNhMHB6Vm0xMGQyVldX a2RhU0dSVVlYcEdSMVJzVW1GVk1rcFlaVWRHV2xZelFrUlpNRnByVW0xR1NFNVZOV2hsYkZvelZsUkdVMkV4VFhoVWEyaFZW MGhDVmxadGVFdGpiR3hWVW01a1ZGSnJOVlpXYlhoSFZtc3hTVkZ1UmxkU2JIQlVWakl4VW1ReVNrbFNiWEJPWW14S2VWWlhk R3RWTWs1eldraFNhbEpXY0U5VVZWSkRUbFpaZUZWdVRsUmlWWEJLVjI1d1ExWlhTbGxSYmtaYVZteFZNVlJzV2xkalZsWnpZ MFUxYVZKWVFqUldha2w0WkRKRmVWSllhR3BTYkZwUFZXcEtORmRzVm5KV2JGcHJUVlpLV1ZsclZuZFVNREZKVVd0d1ZsWnNT bGhXTWpGSFkyc3hWVmRzVm1saWEwbzFWMnhhVjA1SFRsWk5WV2hwVW0xNFZGVnNXbGROTVZwSVpVVTVWR0Y2VWpOWk1GWnpZ VVpKZWxGdGFGWmhhMFY0V2tWYVUyTldUbk5VYld4VFYwZG9ORlpHVm10ak1XUlhWR3RvV2sweWVGWldiWE14VXpGU2NWRnVa RlJXYkZwV1ZrY3hSMVV3TVZoa2VrSlhVbnBXTTFaRVNrdFdiVlpKVW1zMVUwMXVhR0ZXVkVKcllXMVdjMXBHWkZWaE0wSlFW RlZvUTFOV1drZGhSM1JWWWxWYU1GcEZVbUZYUmxwelUydDRXbFpXV1RCWk1WVjRVMGRLUjJKR1VsTk5helF5Vm10a01GUXhU bkpPU0dScVVsZDRjRlZxU205WlZscHlWbTVLYkZac1JqUldWelZMVkdzeFNXRklhRlZXVjFKNlZqRmFUMU5HYTNwalJsWk9V bFJXVEZaSGNFTmtNVTVYWTBWb2FsSlViSE5aYkZWNFRteFplV1JHVGxoaGVsWkhXbFZvUjFSc1NYbGxSbkJXVFVkU2NWcFdX bEprTVZKeVkwVTVUbE5GU2t0V01XaDNWREZTYzFkcmFGWmlhM0JaV1ZSS1UxTXhVbk5XYWxKcVZsUkdTVmxyV25OV1JrbDVW R3BhVjFKdFVucFZNbk13WkRKT1JtRkdaRmhTTW1odlYxWmtOR05yTVVkVmJrNVdZbXR3VDFac2FHOWxSbEpXV2toT1dGWnJO VWxYVkU1M1ZsZEZkMDVWZEZWaGEwb3pWVEJhVjFkWFNrWk9WMmhwVWxaWk1sWnJXbUZoTVUxNVVteGFiRk5GV2s5VmFrbzBW MnhWZDFwSGNHeFdiRVkwVmtkMGQxUXdNVWxSYTNCV1ZteEtXRll5TVVkamF6RlZWMnhXYVdKclNqVlhiRnBYVGtkT1ZrMVZh R2xTYlhoVVZXeGFWMDVXV2tkaFNFNVVZWHBTTTFrd1ZuTmhSa2w2VVcxb1ZtRnJSWGhhUlZwVFkxWk9jMVJ0YkZOWFIyZzBW a1pXYTJNeFpGZFVhMmhhVFROQ1ZsWXdaRFJUTVZKeFVXNWtWRlp0ZHpKV1IzTXhWakZKZUZOdWJGZE5ibEp5VlRKek1WWnRW a2xTYXpWVFRXNW9ZVlpVUW10aGJWWlhWVzVPVldFelFsQlVWV2hEVTFaYVIyRkhkRlZpVlZvd1drVlNZVmRHV25OVGEzaGFW bFpaTUZreFZYaFRSMHBIWWtaT1UxWnNXVEZXYTFwcll6Rk9jazVJWkdwU1YzaFhWbXRWTVdGR1ZuRlNiazVQVW14S01Wa3dW VFZoVmxwWllVaG9WVlpYVW5wV01WcExVbXhhV1dGR1ZsZGhlbFpNVmtkd1EyUXhUa2RYYkd4b1VqQmFiMWxyWkhwa01WcEla VVpPYW1GNlJsZGFWV2hIVkd4SmVXVkdjRlpoTVZwWFdsWmFVMWRIU2taalJUbE9VMFZLUzFkWGRHdGlNV1J6VjJ0YWFFMHll RlpVVmxwTFpWWlNWVkZxVW1wV1ZFWkpXV3RhYzFVeFNsZFdhbFpYVW14YVVGVXljekJrTWs1R1lrZEdVMDB3U2xGWGJHTjRW RzFXYzFwSVNsWmlTRUpRVld4b2IyVkdVbFphU0U1WVZtczFTVmRVVG5OV1ZscHlUbFYwVldGclNqTlZNRnBYVjFkS1JrNVhh R2xTVmxreVZtdGFZV0V4VFhsU2JGcHNVMFZhVDFWcVNqUlhiRlYzV2tkd2JGWnRVbHBaYTFaM1ZEQXhTVkZyY0ZaV2JFcFlW akl4UjJOck1WVlhiRlpwWW10S05WZHNXbGRPUjA1V1RWVm9hVkp0ZUZWVmFrcFBUbFphU0dWRk9WUmhlbEl6V1RCV2MyRkdT WHBSYldoV1lXdEZlRnBGV2xOalZrNXpWRzFzVTFkSGFEUldSbFpyWXpGa1YxTnJXbGRYUjFKV1dXdFZNVk14VW5GUmJtUlVV bXhhV2xsclZURmhSMHBHVm1wYVYxSnNjSEpWZWtwSFZtMVdTVkpyTlZOTmJtaGhWbFJDYTJGdFZsZFZiazVWWVROQ1VGUlZh RU5UYkd4eVdrYzVXR0pHY0VkWlZFNXpWbFV4VjFOdWJGVldSVWt3V1RGVmVGTkhTa2RpUms1VFZteFpNRlpyWkRCVU1VNXlU a2hrYWxKWGVHaFZhazVEVlVad1dFMVZOV3hpUjFKNVZsZDRkMVF4U2xsaFNHaFZWbGRTZWxZeFdrdFNNa3BGVld4U1YwMHdT VEpYVmxKSFpERmFWMU51VWs1V1ZHeHZXV3hrVDA1R1drVlNiRTVYWWxaS1dGVlhlRk5XUjBwV1RsVTVWMkV4VmpOYVYzaFBW MGRPU1dOSGFFNVdNMk41VmxaYWIyTXhWa2RYYTFwUFZucHNWbFp1Y0VkU01YQkhWMnRPVjFKck5UQldSM014VmpGS2NsZFVT bFpOVjFJeldsY3hSbVZXVm5GWGJIQk9UVzFvVVZaR1pEUlRNazV6V2tab2FsTkZjSEpXYlhSTFZsWlZlVTFWT1dsU2EzQklX VlJPZDFaR1dYcFJhbHBhVmtWd1ZGVnNXbmRUUjFKSVVtMW9hRTFXV1RKV2ExcFRVekZrZEZWc1pGSmlSa3BWV1d4Vk1XTXhW bkpYYm1ScVRWVTFXVmt3YUhkaFJURlpVV3hhVm1KVVFqUldSRXBIWkVacmVtRkdWazVXYTNCWVYydGFZVkV4V2tkVWJsSlZZ bGhvVkZWcVFUQk5WbFY0V2toa2JHSlZWalZXYlhSdlZsZEtXVlZ0UmxWV00yaDVXbGQ0YTJOc2NFZFhiWFJYWVRCd1ZsWlVT WGhVTVZGNVVtNU9hVk5GU2xaVVZFbzBWa1pTVmxaVVFteFdiRm93VkZaVk1WWXhTWGRPUkVwWFRXcEdlVlJWVlRWV2JVcEpW RzEwVGsxdGFGRldWM1JoWXpKT1IxVlljR2xTYXpWUFZGVlNWazFzVm5OVmF6bGFWbXRzTkZVeU5VTldWVEZXVFVoa1ZVMVdX bnBaZWtwWFVsWldjazlXWkU1V00yZ3pWbXRTVDJNeFZYbFZXR1JRVm0xb1ZWWXdhRU5VTVhCWVRWVTFUbFpzU2xsWldIQkRW VVphV0dWSWNHRldWa3BVVmtSS1YyTXhTblZSYkZaT1RXNW9WVmRXWkhwbFJrcFhWR3hXVjJGNlZrOVpWRVphVFZaWmVGZHJO VTVTVkd4WFdXdG9UMkpHU2tkVGJFSmFZa1p3U0Zrd1dsSmxiVXBIVkdzNVYySllhRnBXVjNodll6RlJlVkp1VW1wbGExcFdX VzB4ZW1ReFVYaFdiazVxVFd4YVJsWlhjelZoVmxwMFpVaGtWMUpGTlhwV1ZFcEdaREF4V1ZKc1VsZFNWWEJSVjJ4a01GbFhU a2RhUm1ob1pXdEtVVlpzWkRSbGJIQkZWRzA1VldKV1dqQldSelZEVmxVd2VXVkdVbHBoTVZZMFZqQmFhMVpXVG5OUmJFNVRZ a1pXTkZaclpEUlVhekZHVDFaYWFWTkZOWE5WYTFwTFZVWnNjMWR1VG1wU2JFWTJXV3RhVDFSck1VVldWRXBXWWtaS1VGZFdX a3BsUms1MVVXeFdUbFpVUWpOV1JFWlhZekpOZVZaclZsWmhlbXh6V1ZSS05HUXhXa1ZVYms1V1RVUldTRmxVVG5OV2JVcFpV VzFvV2xaNlJsUlpNbmhyWXpGU1ZWRnNRbGRXTTJnMlYydG9kMU14VVhoU1dHUm9aV3MxVlZsVVNtOWxiR3hXVjI1T1YxWnJO VlpWTW5oRFZqRkplbFJxV2xkU1YxSXlXa1JLUjFZeVJrWldiRTVYVWxWd1VWWldVa05qYXpCNFZHNUtZVkpyY0hOV2JGSkha VVphVjFWck9WVmlSbXd6V1RCb1ExWldTWGxQVkU1YVZteHdkbFV4V25kT2JFNXlUMWQ0VjFZelRqWldWRW93WVRGU2RGVlla RTVYUlZwdlZGUk9RMWxXV25KV2JtUnBUVlpLU1ZscVRtdGhSbHAwWVVWd1dHSnVRbEJXUjNoR1pESkdObFJzVW1oTmJXaFVW a1pTUjJReFRrZGFSbXhvVWxSc2MxbFljRmROUmxwR1draGFhMDFyV2xoWlZWWlhWVEZhUmxkc1FsWldSVXA1VkZSR1QyTnNj RWRYYlhoVFltdEtORlpxUmxOVk1WRjRWMnRvYWsweWFGWlZha2sxVFRGc1YxZHRPVlJXYmtFeVZrZHpOVlZyTVVoak0zQldU VzVTZGxaWGMzZGxSMDVHWVVab1dGSXlhRkZYYkdSNlRWZFNSMVZyYUdsTk1sSnZWbTB4YjFOc1pIVmpSWFJWWWtaV00xbFlj RTlXUjBWNVlVaGFXbFl6YUROVk1GcFRaRVV4Vms5Vk5XbFNXRUkyVm10V2EyUnRVWGxTYkdSb1VsWmFWRll3YUVOVlJuQlhW bTVLVGsxVk5YbFpWV1IzVkdzeFJWSnNXbGhoTWxGM1YxWmFTbVF5UmpaU2JGWlRUV3ByZWxkV1dtRmlNVXBYVTJ4V1VtRjZi RmRVVldSNlpXeFZlV1JIZEZaaVZscFhWRlpvUjFac1drWk9WVGxYWVd0S00xa3dXbE5UUjBsNldrZG9WMkpYYUVkV1YzaFRV VEZSZUZaWVpHaGxhelZWV1ZSS2IyVnNiRlpYYms1WFZtczFWbFV5ZUVOV01VbDZWR3BhVjFKWFVqSmFSRXBIVmpKR1JtSkhS bXhoTTBKUlZteFNRMk5yTUhoVWJrcGhVbXR3YzFac1VrZGxSbHBYVldzNVZXSkdiRE5aTUdoRFZsWkplVTlVVGxwV2JIQjJW V3hhUzFaV1RuSlBWa3BPVWpOT05sWlVTakJpTWtaeVRVaGtUbFpzV21oVmFrNVRZVVpXY1ZGdVNrNVdiRXBKV1dwT2EyRkdX blJoUlZwV1lrWktURlpIZUVaa01rWTJWR3hTYUUxc1NsaFhiRlpoWkRKT1YxcEdWbFpoZW14WVZXcE9UMDVHV2taYVNGcHJU V3RhV0ZsVlZuTlpWVEI2VVdzNVYxWkZTbmxVVkVaUFkyMUdSMU5yTlU1WFJVcEtWbXBHYjJJeFVYbFdia3BQVjBaS1ZsVnFT VFZOTVd4WFYyMDVWRlp1UVRKV1IzTTFWV3N4U0dNemNGWk5ibEoyV1dwS1IyTXlUa1poUmxacFZrVmFVVlpHWkRSVE1rMTRW V3RvYVUweVVtOVdiVEZ2VTJ4a2RXTkZkRlZOVlZZeldWaHdUMVpIUlhsaFNFWlZWa1ZHTkZac1duZFRSMUpJVW14T1RsSXpU alJXYTFaclpHMVJlVkpzWkdoU1YzaG9XbGQwZDFsV2NGZFdia3BPVFZVMWVWbFZXa3RVYXpGWlVXdHNWMDFYYUhaV1JFcFhZ MnMxV1ZWc1ZsTk5hbXQ2VjFaYVlXSXhTbGRUYkZaU1lYcHNWMVJWWkhwbGJGVjVaRWM1YVUxclducFpNRlp2VmxkS1ZWSnNR bFZXTTJoTVdYcEdVMU5IU1hwYVIyaFhZbGRvUzFZeU5YZFRNVkY0Vmxoa2FHVnJOVlZaVkVwVFZqRndWbGR1WkdwV2JWSldW bGR6TlZZeFNYcFVhbEpYVWxkU01scEVTa2RXTWtaR1lrZEdUazB3U2xCWGJGcFhZMnN3ZUZSdVNtRlNhM0J6Vm14U1IyVkdX bGRWYXpsVllrWnNNMWt3YUVOV1ZrbDVUMVJPV2xac2NIWlZiRnBMVjFkT1JrOVhlRmRXTTA0MlZsUktNR0l5Um5KTlNHUk9W bXhhYUZWcVRsTmhSbFp4VVc1S1RsWnNTa2xaYWs1cllVWmFkR0ZGV2xaaVJrcEVWa2Q0Vm1ReVJqWlViRkpvVFd4S1ZGZHNX bFpsUjA1WFZteFdWV0Y2VmxoVVZXaERaREZhUmxwSVdtdE5hMXBZV1ZWV1YxVXhXa1pUYXpsaFZteGFlVlJVUms5amJVWklU MWRvYVZORlNrcFdhMk4zWlVaUmQwMVlUbFJpYXpWV1ZXcEpOVTB4YkZkWGJUbFVWbTVCTWxVeWN6RmlSbHBZWXpOd1ZrMXVV bkpXVnpGWFZtc3hXVkpzV2xkU1ZGWlFWbTF3UTJReVRrZFZhMmhwVFRKU2IxWnRNVzlTYkZaelZXdGtWVTFzV2xkWldIQlBW a2RGZVdGSVdscFdNMmd6VlRCYVUyUkZNVlpQVlRWcFVsaENObFpyVm10a2JWRjVVbXhrYUZKWGVHaGFWM1IzWVVac1YxWnVT azVOVlRWNVdWVmtkMVJyTVVWU2JGcFlZVEpSZDFkV1drcGtNa1kyVW14V1UwMXFhM3BYVmxwaFlqRktWMU5zVmxKaGVsWnpW bXhrZW1Wc1ZYbGtSM1JXWWxaYVYxUldhRWRXYkZwR1RsVTVWMkZyU2pOWk1GcFRVMGRKZWxwSGFGZGlWMmhIVmxkNFUxSXhV WGxTYkZwb1pXczFWVmxVU205a2JHeFlaVWhrVkZKc1NqQlVWbFUxVkcxS1JtTkljRmRTVjFJeVdrUktSMVl5UmtaV2JFNVhV bFZ3VVZaV1VrTmphekI0Vkc1S2FGSXpRazlVVlZKSFZteGtjbHBFUWxwV2Eyd3pXVmh3UjFaV1NYbFBWRTVhVm14d2RsVnNX a3RXVmtaeVQxWmFUbEl6VGpaV1ZFb3dZVEZXZEZac1drNVhSVnBYVm10Vk1WUXhXbkZSYm1ScVVteEtTVmxxVG10aFJscDBZ VVZhVm1KR1NreFdSRVpHWkRKR05sUnNVbWhOYldneVYxWmtOR1F4VGtkVmJsSk9WbFJzVDFsclZuZGxiRnBHV2toYWEwMXJX bGhaVlZaeldWZFdjbU5HUWxkV1JVcDVWRlJHVDJOc2NFZFRiWGhYVmtWYU5GWnNXbE5VTVZKelYxaGthbE5GU2xaVmFrazFU VEZzVjFkdE9WTldhM0JXVlZkek5WWnJNVWhqTTNCV1RXNVNjbFpYTVZkV2F6RlpVbXhhVjFKVVZsQldiWEJEWkRKT1IxVnJh R2xOTWxKdlZtMHhiMUpzVm5OVmEyUlZUV3RhVjFsWWNFOVdSMFY1Vld4T1lWWnNWalJaTVZwWFZsWlNjazVXWkU1VFJVb3pW bXRXYTJSdFVYbFNiR1JvVWxkNGFGcFhjekZWUmxaVlVXNUtUazFWTlhsWGExcExZa1phVlZKdWFGZFdiRXBRVmtkNFdtUXlU a2xSYkZaVFRXcHJlbGRXV21GaU1VNVhZMFJhVldGNlZuTldiR1I2Wld4VmVXUkhkRlppVmxwSFZERldWMVl4V2taalJUbGFW ak5vYUZwRldsZFNNVkp6VkdzNVYySllhRnBXVjNodll6RlJlVkp1VW1wbGExcFdXVzB4TkdSV2JGZFhiVGxUVm14d1dsZHJW bmRoUm1SSVlVaFNWMDFHU2tSWFZscFBZekZXY2xkc1pHbFdia0poVjJ4YWEyVnJNSGRpU0VacVRXNVNXVlZzVWtkU01WbDVZ M3BXVTFack5VZFZNbmhMVmxVeFJtTkZUbGRTUlZwTVZYcEdZVkpzVm5KV2JHaFhZbFpLYUZaV1dtRlJNVlp6VjI1S1ZXRjZW bGxWYTFKRFkwWmtSbFZyV2s1U1ZFWjZXa1JPYjFReFNrWlhiWEJWVm14S1lWcFhlRzlUVm5BMlUyczVWMkp0WTNkV1JtaDNX VlpyZDA1WVJsWmlWVFZQVm10VmQyVnNaRVpWYTFwT1VsUldTRnBFVG05VU1VcEhWMjF3WVZaV1NtRmFWM2h2VWxaS1ZWSnJP VTVYUjJOM1ZrY3hkMVV4YTNkTlZsWldWa1ZhUzFsWE5VOWpiRnB4VW14T1ZVMVhVbGhWVjNSelZrWmFWMU50YUZaV1JWcE1W VEo0VjFJeFRsVmlSWEJwVTBkamQxWkhNWGRoTVd0NVZtdFdZVkpWY0ZwVk1HUnFaVlpSZUZkcVVrOVNWRlo1Vm0weFQySkdT a2RoTTJ4WVVsZG9kVlJYZUVabFIxWkZWV3M1YUdFeGNIRlhiRlpUWVdzeFIyRkZiR0ZsYTNCUVZsUkNjazB4VmxaYVJtUk9Z a2Q0V1ZwRVNUVlRiVVp4V2pOS1ZGWXljM2RaVkVaYVpVWldjazlXYUZkaE1IQkxWbFJHVjFVeGJGZFNXR2hVWVROQ1YxVnRk SE5rYkZKSllraGFZVTFJUWtoWmExWXdWa1phVm1ORmRGZFNiSEJJVldwR1QxSXhjRFppUlhCcFZsZDNNVlpHV210VWJWRjNU VlpXWVZJemFFOVpWM04zWld4a2RHTkdTazlXYmtKSlZrWm9kMVJzV2tkWGJrWlZWbTFTYUZsVVJuTmtSa3BWVTJ4d2FHSldT bmxXUmxaVFZHc3hWbUpJUm1wTmJWSk5XVlpTYjJOc1dYZFdXR2hUWWtkU2VWUXhWbGRXUmtwV1kwWk9WMUpGU2t4VlYzaFNa VVpPY21SR1pGTldhM0JIVm1wR1lXRXhaSE5TYkdSU1lrVndXRmxVUVRGVU1WbDNWRzAxYUZZeFNucFdNalZQVkRGWmQyRjZS bUZTVmxwNldsY3hVMk5YUlhwWGJVWk9WbFZ3TlZaclVrTmhNbEpHVFZWa1lWSXlhSEpVVlZKV1RVWndWbFp0Um14aVJUVkpW VEo0UzFsV1duUlBTR3hYVWxad1VGcEhjM2hrVjA1SllrWm9VMVpXVmpOV2ExcGhZVEZhUjFwR2FHdFNiSEJVVld0YVlVMUdi RlZTYkU1c1lrWmFTVll5TUhoWGJVcHpWMnBTV21KSGFETmFSRXBPWlVkT1NFMVdUbE5OVm13MlZUTndRMk15VFhsU1dHeFZZ a1pLYjFsWGVITk5iRkp6VjIxR2FFMVhVa2haVldoUFlrWktSMk5GVWxoV00wSkRXbGR6TVU1Vk9VVlViR2hvVmtkME0xWnFS bTlaVjFKSFUycFdVRkpGV21GV2EyUXdUV3hrV0dOSFJtaGlSa3BHVlcxNFEySkhSWGxsUlU1VllrWndVRlpXV25ka1JscDFW bXQ0VGxKc2NGSldSbHB2VmpGV1NGVlliR2xTVkVaVlZUQmtOR0ZHYTNsT1ZUbFZWbXhhVmxscldrTldWMHBWVmxod1lWTklR bkpVVjNoWFYwZFdSazlWTlU1aWJWRXlWMWMxZDJJd01YSmtNM0JTWVRGS1VGUlVRbFpsUmxwMFpVYzVWbFl4V2twWmFrNUxW bXhLY2xOclVsZGlSMUpvVkZaYVlXUkhUa1ZSYkU1WVVtdHZkMVpyWkhwTlJURllVbGhvVW1KdGFITldhMlJ2VFZaWmQxZHJU bXROVlZreVdXdFZlR0ZYVm5SVmExcFhWbGRvUjFSc1dsSmtNRGxaVm1zNVZGSlVWazlYYTFacVRWWlplVk5yWkZSV1JWcFVW bTAxUTFkc1VsbGpSVnBPVm0xNE1WVXlNVEJVTWtwWVQxUktWVTFXVlRGV1ZsWXpaREZ3Um1WR1drNVNhMVkyVjJ4YVYxWXdO VlpQVlZwcVVteGFVRlJVU2xOT2JGcFdWV3R3YkZac2NIZFVNVlUxVmxaYVJtTkZNV0ZXTTBKUVZHdGFhMWRXUm5OalJrSlRU V3MxTlZZeU1IaE5SbVJJVld4b1ZHRXpVbFJVVnpFMFRWWlJlRlZyV210aVIxSkdWV3hvYzJKR1NYaGpSVFZZWVRKb1QxcFdW VEJrTWtZMlZHMW9UbEpzY0UxV1ZFSmhVakZOZVZKWVpGcE5NbEpZV1d4YVMwMXNVa1ZUYWtKVFVqQTFlVnBWYUVkWFIwcElX bnBHV0dKRk1ERlpNakZUWTFkS1JrNVhSbXhoZWtGM1YxZDRWMU15U1hsV2JHUlZZbTFvVVZadGRHRlhWbXh6VjIxR1ZWSnVR bGxXUnpWTFZqQXdlRmRzVmxkTlYyaElWR3hhYTFZeFRuUmxSbVJwVjBVeE5GWkhkR3BsUjAxNFZteGFXR0pyTlZsWmJHUlRV VEZXTmxOdVpFNU5iRXA2VmpGb1lWVXhaRWxSYlVaaFZsZFNWRmxVU2twbFJtUjBVbTFHYUUxV1dYbFdNV1EwWWpKS1ZrOVdi R3BTTTFKWVZGZDBkMDFzWkZoTlNHaFhZa1phTUZaV2FHdFVNREZIVTI1b1YwMXVRblZaTW5oVFZtMUtTVlpyTlZkbGEwa3lW MVpXVjFkck1WWk5TR1JZWVRGd2FGWnJaRzlVUmxwelZXeE9hRkl3V2pCVVZsWjNZa2RLV0ZWcVZscFdSVnBZVmpKek1WWlhS a2hsUmxaT1lXMTRXVmRZY0VOa01sWklVMWhvVm1KdFVsbFdha0V4Vkd4V2RHVkZXbXBpUm13elZrZHdSMWRHV1hkWGJsSlhU VWRTVkZWNlJrOWpiVXBGVW14S1RsSldjRXhXVkVKWFVqRktkRkpZYUdGU2EwcFpWbXhvUTFFeFVuTldiWFJXVFZaYVdsWldV a05XUjBwelVtNXNWMUpGTlV4Vk1qRkdaVlpXZEU5V1VsTk5NazQwVjJ4YVUyRXhWWGhUYmxKVFlUTkNiMWxVU205alZscEhW V3hrVjFKck5WbFdiWGhIVjBkS1ZtTkdaRlZOVjFKVVdWVmFkMU5IUmtWVWJHUnBZVEowTkZadGVGTmpNazVYVldwV1VGWlZO VmhWYkZKR1RXeGFTR0pFUW10TmExcEdWbGR3VTFac1drZFNWRVpXWWtkUk1GUnRNVmRUUjA1R1ZtMXdhVmRIVWpWV1ZtaDNZ bTFXUms1VldsaGlWRVp4VmpCV1MySXhXbFpYYkdSWFVqRmFTVlp0ZEd0V01rcHpVMnRPWVZaWGFGUldWbFV3WlZaS2NWSnJO Vk5OTURCM1ZtcEdWazFXV2toVmJrWnBVbGRTV0ZsclpEUlNSbHB4VW14a1ZFMXNTVEZVTVdONFZqSkZlVlZZYUZwaE1sSklX a1JLVG1ReVRrZFhiWGhYWWtoQ1dsZHJVa2RaVjBaelYyNVNZVkpWY0hGWldIQlRUVEZzY21GSVRsVlNNSEJZVm0xMGQxWkdT bGxSYTNCYVRXNW9TRlp0ZUVabFYwNUhVV3hDVkZKdVFucFhWM2hoVWpKV1JrMVZiRlJoZW14dlZXMTRTMlJXV2xaV2JFNVdW bXRXTmxsVlZqUlViRXBYVjJ4Q1ZVMUdjRkJVYTFwclZqRmtXVnBIYkZkTmJFcFFWakZTVDFack5WZGlTRlpVVmtWd1dGbFVT alJXUmxsNFZsaG9UbFl3YkROVk1uUTBWMGRLVlZvemFHRlNNMmg2VmtaVk1HVnNVbkppUjBaWFZsUldWbGRyVWtkak1ERnlU bGhHVjJKcldsWldibkJ6VWpGYVNHVkZaRTlTYkhCNVZrZDRkMkZWTVZaWGJIQllWa1ZyTVZscVNsTlNiRnAwVGxaV1RtSllh RWxYVkVwM1ZqSldXRlZzVmxKaGEzQlVWbXBLTkdNeFVYZGFSMFpYVm10d2VWUlZhRzlVTVU1SlVXeENWbUV4U25KWmJYTXhW MVp3UjFac1VrNVNlbXQ1Vmxkd1MxbFhTbk5XYkZwc1VucFdUbFJWVm1GVE1XUlZWR3RrYW1KVlduZFVNV014VjJ4a1JsTnFX bHBoTVVwMldWZHplRkpzVW5WUmJHUlhUVEJLTkZac1VrOVRNVTVZVm01T1ZXSllVbk5WYlRGVFZWWnNWVk50UmxaV2ExcFlX V3RrZDFVd01IbGtla3BZWVd0YVZGWXhWak5rTVZweFZtMTRVMUp1UWxWWGJGcHFaVVpTYzFkcldsTldSbHBvVkZWU2MxSldh M2hXYWxKVlZqQndWMVZ0ZUdGV1IxWlpWV3hHV0dFeFNtaFdha1poWTIxU1JWUnNVbWxXTW1oNVZtMTBVMVJ0VG5KUFZsWm9U VEZ3Y2xaclpHdE5NV3Q2WTBkd2EwMUlaRFpWYlhoWFlVWkplVTlZYkZwTmJsSllWRzE0WVdOV1RuTmpSa0pYVWxad2VGWnRN WGRoYXpGSVZHeGFUMVl6YUU1YVZsSnpaVlphZEUxWVpHbE5iRVl6VlRKNFlXSkdTa2RYYWtwVlRVZE9ORnBFUVhka01YQkpZ a2RzVkZORlNsZFdiRkpMWkcxV1YxZHFXbEpYUjNob1ZsUk9VMlJXYTNoV2F6bHBUVmhDU1ZsVlVsTlVNREZaVVc1b1ZrMUhV ak5aVlZwTFYwZFNTRTlXVmxOWFIyTjNWakp3UzFNeFdsWk9XRlpZWW1zMWNGWnJXbmRrVmxaMVkwZEdhRkpyV2pCVmJYaEhW REF4UmxaWWNHRldiSEJNV1RCYVUyTnRTa2xpUm1ocFlsUnJlVmRzV2xkak1sWnlUMVphVDFOR2NGbFdiWGhoVFVaYWNtRkZP VlJOVmxZelZUSjRhMVJ0U2xsUmEyUlhZVEpTV0ZkV1drdFhSVEZZWkVad1YwMXRaekZYYTFKRFZUSlNWMkpJUm1oU2JGcFdW V3BLVTAweFdYZFVibkJQVmpCd1dsWnNVbGRoVlRGWVpVZEdXbUV5VWxCWmFrWkhZMjFPUms1WFJrNU5SRlpLVjFab2NrNVdW a2RVYmtwc1VrWmFVMVJWWkc5VFZteDBaRVprV0ZJeFdscFdNbk0xVkd4T1NGb3piRmhoYTBwNVdsVmFTMUpzYTNwWGJFcFhW bFpXTTFaWE1UQlhiVkY0VjJ4YVVGZEhlSE5WTUdoRFVteHNXR1ZGT1ZOTlZUVktWMnBPUzFkR1NsVmlSbFphVFROQ2RsVnFT a3RXTWtsNlUyeFdVMVpyYTNsV1YzUlRZekZaZUZSclZsUmhiRnB4V1ZST2IxUnNiRmRVYWtKcVRWWmFTVlJXWTNoVWJHUkhW MnRzVjJGck5VUldWV1JMVmxaYWRHRkhiRmROTUVwWVYxUkdUMDFHWkhSVWEyUlVZbFJzVlZwWGMzZE5WbEY0V1ROb2JGWnJW ak5XVm1oclZEQXhjVkZVUmxwV01uTXhXVmQ0WVZaV1NuRldiR1JYVWpOb1RGWnNWbTlaVmxaV1RraGtUbFo2Vm05VVZ6VlRZ MFpXYzFkck5XeGlSV3cwV1ZWV2QxVXhTbGRTVkVaYVRXNVNkbFZ0TVV0ak1XUlZVV3hDVjAxc1NsTldhMVpYWVRGU1dGVnVU bEpoTUhCV1ZGWmFZVlpHYkZobFJuQnNZWHBzV2xscVRrdFdSMFY1WlVoU1YwMXFRalJXUkVwSFUwZE9TVlJzU2xkU1dFSXlW VE53U21WRk1VWk9WV3hoVFROQ1dGbHRNV3BOVm5CRlVtczVhRTFzV2tkVU1XaExWMGRLZEZWclRscGlSbkJ4VkZkNFIyTldX bFZSYlhScFVteHdSMVpHWkRCVU1sSllVMnRvYWxKck5VOVpiVFZEWXpGa2MxcEVUbXBpVlZwSFZUSTFUMkZ0Vm5OaU0yaFhZ VEpTVEZWcVNrZGtSbHBWVm14Q1ZGSXlaRFpXTVdRMFl6RmtkRlJyVmxSaGF6Vm9WakJXZDJOc1draGtSVGxPWWtkME0xcEZW bmRXTWtwV1kwUldWMkV5YUVoV1ZtUkhVMFprYzJGSGVGZGxiRnBXVmtkd1IyUXlSbk5hUldSU1ZrWmFWRlJYY0ZaTlJscEpZ MFZ3VGsxV1NsWldNblJUVmxaYWMyTkZNVlJsYTJ3MFZHdGFhMVpyTlZWVGJGcG9ZbGRqZUZZeFdsTlJiVkY0VjI1S1RsZEdX bFpaYkZwMlpERldjbUZJVGxkV1ZGWllXVEJTVTFaWFJuTmlNM0JhWld0ck1WUnJaRTlUVmtaVlUyeFNhVmRGU2taWFZsSkhV bXN3ZUZkc1ZsZFhSbkJXV2xkNGQxbFdWWGhaZWxaclRWWndXVlpITld0aVJrbzJZa1phV0ZadFVuSlpla1pMVjFad1NWVnNW bGRXTVVwb1YxUkdWazFXUlhoU2JrNW9VbGhTVDFsc1pHOU5WbEpYVjJ4YVQxSnNWalpWYlhSVFlWZEdjMWRxVWxaaVZGWkRX bGQ0YzFZeGEzcFhiRnBYVWpGS05WWkZhSGRpTWtwSFYyNVNUMU5GY0hKVVZ6RjZUVlpzZEdSR1dteGlSVFZhVlcxNGIxUlZN VmRUYkdSWVZucFdjbGt4V2xkak1WWjBUbFpDVjFacmNIbFhhMUpMWVRGU1YxUnVWbWhTYTNCT1dsY3hiMDVXWkhOWGJFcHNW akExUmxsVldsZFVNREZXVWxSQ1YySkdTa2haYWtwTFUwWndSVlZ0ZEU1V01VcEhWMnRhVTFFeFRsWk5XRTVXVmtWYWNGUlVT bTlOUmxaWVpVYzVhbUpWY0VoWmExcFhWREpGZVU5VVdsWmlSbHAyVmtSR2RtVlhVa2xUYlVaVFRVWndWMVpzVWtOaE1WWkhW bXBhVW1FelFtaFphMVozVmpGc1YxcEdXazVOUkZaSVYyNXdWMVZ0U2tkU1dHaGFUVmRvU0ZaVVNsZGpWa3B5Vkcxd1RsWllR bEJXUkVaaFZqRmtSazFJY0ZKaVZFWlFXV3RrTkUxV1VuUmtTR1JYVWpCc05sbHJZelZVTVZwV1lrUk9WbUZyU1RCWk1WWTBU bXhrZFZKdGJFNVNSVnBXVmtjd2VHRXhUWGROV0U1VFYwZG9XRll3WkZOWlZtUnlWMnR3VDFack1UUlpXSEJMVjJzeGMxTnRP VnBXTTBKRVZGZHpNV05zV25OVGJFNXNZVEJ3UlZkWE1YZGliVlpXWkROb2FGSllhRTlhVnpGdlYxWnNjbHBHU2s1U2JrSmFW VlpvWVZVeVNsZGpSbWhhVmtWc05GUnRNVmRXYkZweldrWkNVMkV4YnpCV1YzUnZVVEZhYzJORmFFOVRSM2haVlRCb1EwNUdW bkpYYlhSWVZsUkdWMVJXV2s5Vk1WbDRWbGhvVm1KVVZsTlVWRVpYWXpKRmVtRkdWbGhTVkZJelYxWmtkMWxXV2tkVWJHeGhU VEo0V0ZadWNITk5SbXQ1VFZaT2FFMVdXbGhXUnpWelZrWktjazVWVmxkTlYyaDJWbTE0YTFkRk5WVlNiRTVwVmxSV1VsZHJV a0pPVjBsNFZHdHNhV1ZyY0ZoVVZ6QTFUa1p3V0dGNlZsZE5hM0I1VkRCb1lWWldXbGhsUm1oWFZrVndWRlY2UmtkWFIwcEhW MjFvVTFKc2NHOVhWbU14WVRGV1dGSnVTbXhTUlhCUFZXeFNSMDFzYkZoTldFNU9VbXMxVmxac1VrZFpWMHB5VTI1S1YxSkZS alJhVjNoT1pXeHdTVmRyT1dsU01Va3hWa2R3VDJFeVVuSk5XRkpXWVRBMWNGbHNVa1pOYkZsNFlVVTVhRlpzY0VkVk1qQjRW VEZhUmsxSWNGZE5ibWhFV1d0a1UxTkhSa2RYYlhSb1RWYzVORlpzVWtOa01XUlhWbXRvVkdGNlZsUldNR1JQVFd4V2NscEZP VmhXTVZwWFdsVm9ZVlJ0U25OVGEzaFhVbTFTZGxVeU1VOWpWbEp6V2tVMVRsWllRbFZXUnpCNFZESk5lR0pJVGxkaVJWcG9W bXBLTkZac2JGWlhhelZQVmxSR2QxcEZhSE5XVlRGSlZXMUdXbUV4V2pOWmEyUlBVMVpLV1ZwSFJtbFNXRUpoVmpJd2QwNVhU WGRQVm1oc1VtdGFiMVJYY3pCTlJscEZWR3M1V0dKVk5VaFdWelZ2VkcxS2NtTkdRbFZpUjAxNFZrVmFjMk14VW5OVmJFNVNa VzEzZVZaR1pEUmlNVTVXVGxoV1dHSnJjRmRXYkZwWFRteGFjVkp1VG10aGVrSTFWVzEwYjFVeFZqWmhSRXBZWWxSV1ZGWXll R3RqTVhBMlVXc3hiR0pYYUZKWFZscFhZekpTZEZSdVJsaGlWVnBXV1Zod2MwMVdVbkZSYkU1c1ZqRktWMVJWYUhOaVJrcFpZ VWhPVldKSFRqUldhMlJUVTBad1NWRnJOVTVpVlRCM1ZsaHdRMWxYVm5OVGJGcHFVbnBHY0ZadGN6RmpSbXh5V2toa1RrMXJO VEZaTUZwcllWWmFSMWRxV2xkU1ZUQXhWbTB4VW1WR1RuRlNhemxUVWxSV01sZFdWbE5oTWxaWVZtdGFhRkpHU2xsVmFrWjJU V3hWZDFwR1NtcGlWbHA0VjJ0U1IySkdTbkpPVkVKaFVrVnJNRnBYZUVabFZrNTFWMnh3YkdKWWFGWldha3AzVjJzeFYxSnVT azlUUjJoVVZXeGtiMWxXVmxWUmFsSldUVVJDTkZaWGNFdFZSbHAwWlVaU1YySkhhRE5aTUZwVFUwVXhXV0pIUm1oaGVsWkxW bXRqTVZZeGJGZFdhMnhXVmtaS1ZsbHRNWHBsUm1SWFZtdDBhRTFzU2xoV2JYQkhZVlV4ZEdWR2JGaGhhelY2V1ZSS1VtVnNa SFZUYkZwb1RUQktXbGRYTUhkbFIxWnpWVzVPV0dKR1dsRlZiWFJoVm14VmVXUkVVbFpXV0dRelZsZDBVMVpYUlhoVGJFNVlZ a2RTV0ZSc1ZURldWMFkyVkcxR2FXRjZSVEZXUkVaaFVqSkplRlZzYUZkaGJGcFpWbXRrVTFWV1VuUmpTRTVZVWpBMVYxUnNa REJVYkVsNllVVjRWVk5IY3pGYVJXUkhWakZTY21SSGFHaFdSM2haVjFSS01GbFdXWGhYYTJ4WVlrZG9jVlZzWXpWTk1WSnlX a2M1VmxaVWJFbFdNbmhoWVRGS05tRXphRmRoTURSM1ZYcEdZVkpzVGxsaVJuQnBZbGRvYUZaSGVHdE5SbEYzVFZaa2FWSkZX bkJXYWtaV1pXeHdSMVZ0T1ZWU2JGcEdWVmR6TlZkdFNsZFRhbFpWWWtaYWRsUldXbGRrVjA1SVpVWmFhRTFzU25sWFZFWmhZ V3N4ZEZWc2FFOVdlbXh6V1d0V1MxbFdXa1paZWtaVlZqQTFlbFp0ZEZkWGF6RldVbXBXVjAxdGQzZFdWekZQVm1zMVdXSkhS bWxpVjJnMFZtMTRVMVV4U2taT1dGWm9Vak5vY0ZacldtRlNWbFpZVFVSR2FVMXNTbFpaVldNeFZHMUZkMWRVU2xoaVdHaDJW RmQ0WVZOV1JuTmpSMmhUWWxob1NsWlVUbmRqYlU1eVRsVm9VRll6YUZsVk1HUlRVMnhSZUZadVpGZGlWa3BHVlRKNFQxWlZN VmxSYkhCWVlrWndjbGRXV2xkalZsSnpZMFpDVTFkR1NrdFhWRUpXWlVkR1dGUnVUbGRpYkZwVlZXdGtORlJzY0ZaV2FsSlBV bFJTTmxadGNFZFViVVpWWWtSR1YxZElRbEJWYTFVeFpGWmtjMVpyTldoTlZtOTVWbXhqZUUxR1VrZGpTRXBVVjBkb1VWWnRN Vk5YUm14VlVXMUdhMDFWTVROYVZWcFBWVEZhVjJOSFJscGlSMmhVVlhwR2ExTkdVblJoUmtwcFlrWndkMVpXVWtKT1YwcEhV MjVHVkdKR1duSldibkJUWlZaT05sUnROVTlTYkhCSVYydGtORlpXV2toaFJFcFdWa1UxWVZSc1pGZFhSVEZaVjIxd1RsSlVS VEJYVm1ONFZURldjbVF6WkZaaGVsWldWbXRhUm1WV1dsWldiVVpWVFZVMU1GUXhXbE5oVjBWNlVXcFdXbUpIVGpSVmFrWnpZ MWRHUmxack5XbFNWRlo1VjFaa01FNUdSbk5VYTFKclVrVndjVlJYZUV0a2JIQkZVbTVLYTJKVmNIbFVhMUpYVmxkV2MxWllj RmRXZWxaRVZqRlZNVmRXVm5WaVJUVlVVbGQzZVZaRVJsTlRhekI0V2toV1lVMHlVbk5aYTJoRFkyeGtWVkpyV2s1V2JGcDRW bGQwVDFSdFNrWk5XR3hYVFVad1dGcFdXbUZXYXpGRlUyMTBWMUpyY0hsV1JFSmhWVEZhV0ZWdVZtaFNWMUpYVld4YWQxTnNW WGxoZWxKcllraENTbFV5ZUhOaVIwVjRZak53VlZOSVFuWldSM040VmpGV2NWTnJOVk5TTTJoaFZtcEdZVll4V2toVmJHaHJa V3RLVkZac1VsZFNNVnB4VW10S1QxSnRlSGhaVlZaUFYwWmFWMk5GY0ZkU1YyaFlXVEZrVjFJeFZsbFhiWFJPVmxSV05WWkdW bTlrTURGelZteGFhbE5HV2xOWlYzaGhVbXhTV0UxSVpFNWlWVnBKV2tWV2QyRXlSbk5qUlhSVllsaG9lbGt3V25kV1ZrNVZW V3hrVG1KR2NFcFdWelYzVmpBeGMxZFlaRlpoTUhCV1ZWaHdiMDB4YkZkaFNFNVhWakJzTlZSclVrZFpWa1kyWWtWNFdtRXlU VEZhVjNoUFYxWmtkR05GTlZkaE1YQlpWbFphVmsxV1drZFVXR3hWWVROU1ZsbHJXbUZrYkZweVdUTmthMkpGTkRKWlZWWlBW akZPUjFKWWFGZFdNMUo2V1hwR2RtUXlTa2hqUmxKWFYwVktlbFpFUW1GVU1rWnpZMFZzYWxOSGFGZFpWRW8wVVRGcmQyRkZk RmRXYkVZelZXMHdOVlJyTUhkU1dHeFZWbnBHZWxacVJuZFNNa1pKVTIxc1UyVnRkekJXVkVKdlV6SktjMVJzYUZaaGJGcHlW VEJrTkZaR1pISlZiVFZQVmxSV1NWWlhNWGRXTURGeVYyeFNWbFo2VmpOVWJHUlBWbTFXUm1KSGFGZE5hbWd6VmtaU1ExUXdO VVpOVmxaV1YwVndjMVp0ZUhkVWJGcEhWMjVPVWsxV2NGaFZWM0JoVm14YWRHRkhPVlZoYTNCVFdsVmFTMk14V2xWV2F6VlhZ VEJaTVZkV1kzZE5WazVIVWxob2FGTkdTbkJVVldoVFZFWmFWbFpVUm1saVJuQldWbGMxVTFadFJuSk9WazVXVFc1Q2VscFda RXBsYkVwMFpFZDBhRTFFVm1GWFZFSnJUVVpKZVZScVdsWmliVkpXV1Zod1IyUldXbk5WYkU1V1ZqRmFlVmR1Y0ZkVU1sWnlU bGhvVldKVVJtaFpNR1JYVmpGV2MxWnRiR2hXUjNoUlYyeGtkMk15VWtkVWExWllZbFJXVDFscldtRlZiRlp4VTFSV2ExWXhX bmRhUldSM1ZHeEtSbGRxUmxkU2JIQlFWbXhhVjJSR1VuUmpSbHBvVFZWd01sZFVSbUZVTWtwWFlqTmthazB5ZUhOV2JGcExW R3hhUmxremFHcFNWRVpHVm0xNFExWnRSWGxoUmxwYVltNUNXRlpVUmt0WFIwbDZZVVpTYUdKRmNGVlhWbHBoVVRGa1dGTllj RmhoTVhCVVZqQmthMDVzV2tkVmJFNVVVbXRXTTFSV1ZtdFVNREZXWTBaYVZrMVdXbmxVVldSTFUwZE9SVlZyT1ZoU00yZzFW akowVTJJeVRsZFhhMUpRVm5wV1ZGUlZVbk5XUmxWNFYydDBhMkpGTVRaWGEyaERZVEF4Y2xkdVpHRlNiSEJQVkZWa1YxSXhj RWRXYlhSb1RVaENXbGRYTUhoaU1EQjVVbGhrVldKclduSlVWM2hHWkRGU1YxcEVRbFZpUjNRMVZGWm9SMkV3TVhOWFdHaFlW a1UxUTFSVldsTmpiVVpGVm14S1RsSkZWWGRXYlRCNFlqSldkRlJyWkZoaE1YQlZXV3hrYjAxc2JIVmpSemxyVm14d1NsbHJZ elZXVjBaeVYycGFXbUV5VGpSYVZWcDNVMFUxVm1ORk9XbGlhMHBTVmpKMGIxSXhXWGhoTTJSV1lXczFUMVpzV2t0VGJGSlZV VzVrVldGNlJsaFpWV2hyVkRKS1NHUXpjRlZUU0VKTVZYcEtSbVZzY0VkU2JYaFRVak5vTTFacldsZGpNa3BIVld0YVZGZEhV bkZVVlZKdVRVWndWbFp1U2s1aVJrb3dXa1ZTUzJGck1IbGhSRlpWWVd0S00xWXllSGRPYkU1elZHeEtUbEpGVlhsV2JGcGhX VlpTYzFSdVVsZFdSVnBUVkZjeGIyUkdXbFpYYTA1cVVtczFNRlV5ZEhOV1ZrcFdWMnhhV2sxV2NIWldSVnByVjBaS2MxcEhl RmRTTVVsNFZrUkdZV1F4VmxoU2ExcFFWbGhvVjFVd1ZURk5iRlkyVTJ0MFZGWnRVbGxVYkZaM1Yyc3hSV0pFV2xwV1JUVmhW RlZhU21Rd09VbGFSMmhYVWxWd1VWWlljRXRXTWs1eVpETmtWMWRHY0hCWmJGcGhaR3hrY1ZOc1RsaGlWWEF4V1c1d1YxVXhT WGRPVmtaV1pXdEtkbFY2U2t0V1IxSkZWV3hLYVZaRldtRldSbEpEVmpBeGMxcEdiRk5oTVhCaFZGZHpNVlJHVlhoYVJUbFRZ a1UxUjFWdGRFdGhWVEZ6VTJ0YVdrMUdXbGhWTUdSWFkxWk9jbVJIZEZkTmJXZDVWbXRvY2s1Vk1WZFNibEpUWVRGS2FGUlZh Rk5VVmxaWlkwWmFUazFyV2xoVmJUVnJWVEF4Vms1V1NtRlNla1oyV1cxNFUxWnNWblZoUmxaV1RURktWVmRXV21GWlZtUnpW VzVTYUZKNmJIQlVWVnBXWld4a1YyRkhPV3RoTTA0MVdUQlNZVmRyTVVWV2FrNVhUVVp3TTFVd1dsZFRWazV5Vkd4a1UwMHlh RkJXVkU1elRVZEplVkpyVW10VFNFSnZWRlpvUTFSR1pIUk5WVGxwWWtVeE0xWlhkSE5VYkZsNlZXNVNWV0V4Y0hwVmExcEta REE1V1ZSdGFGTk5ibWN5VmtjeE5GVXlTblJTYms1VlZrVndZVlJWVm1GVVJsSlhXa1YwVjFJd01UUlphMXBQVlVaS2NsZHJW bFZXUlVwaFdUSjRUMUpzY0VkVmJXeFlVak5vVmxkV1kzaFZNVkY1VTJ0YWExSlhhSEJWYkdoRFl6RldjMWR1Wkd0U01GcFhW VzAxVjFSck1VZFNXR2hhVFVaYVMxcEVRWGhTYlVaSFkwVTFhRlpIZHpCV2JYQlBVVEF3ZUdORldtaFRSa3BWVld4U2IwNXNi SE5XYlhSb1ZqQndXRmxyVWs5VmJVVjZWRmh3V0ZadFVuSlViRnBYVjBaYWRGSnRhRmRoTVc5NVZteGFhazFYVW5OaVNFNXBV bXRLVTFsVVRtcE5SbXgwWlVkd1RtSklRbmxXYlhoaFlVWktjMkpFVmxWaE1sSlFWakZrVW1WVk1WbGpSMFpUVFRGS1dsZFdh SGRSTWxaSVZteFdhRkp1UW05VVZtUnVUV3hrY1ZOdFJsZE5hMXBLV1ZWb1MyRnJNVmxSYXpGWVlUSlNjbFpIZUdGa1IxSkdU bFpPVTFadVFYaFhWRUpXWlVaS2MxTnNVbXRTTTBKWFZGUktVMDVzYkhKWGJtUldVbFJXV2xaWGN6RlhSa3B5VGtod1dGWkZT a2hXYWtwTFVsWldkR1ZGT1ZOV1JWcElWako0YTJJeFNuSk9WbEpRVjBWYVZGUlZVbTVsUmxGM1draGthbUpGTlZaWmEyaFBZ a1pLY2xkc1pGZGlWRVp5V1RJeFNtVkhTa2xUYkdSVFVqSm9WVlpxUm10VU1rVjNUbFpXVW1KdGVGaFdhMVpLWlVaYVIxVnNU bE5XTURFMVZqSndWMVpGTVhSVVdIQllZVEZ3VkZsdGVISmxWbEpWVW1zNVRrMVlRa1JXYTFadllURmtjMkpFV2xkV1JVcHhW RlJHWVZKc2NGaE5XRTVvWWxaYVdsVXlkSGRaVjBweVYxaHNXbFpXU25wVWJHUlRZMFU1VjFkdGVHbFhSMDE0VjJ0U1IxRnRW a1pOVm14cFUwWktXRlZxUm1GVlZsbDVaVWRHVjFZd01UVlViRll3Vm14SmVXRkZWbGRXZWxaaFdrZDRhMk5yT1ZsU2JVWlha V3RhVGxaWGVGTmhNa1pHVGxWb1UxZEhlRzlVVlZwaFVteFNjMVJ1Y0d4V1ZHeFpWakl3ZUdFeFdrZFRhM1JWWWxob1lWcEVT azlXVmxKMFpFZDBhV0pYVVRGWFZFcDNWakZzVms1SWNGWmlSVFZQV2xab1RtVldaRmRYYlhSc1ZteGFXVmRyVmxkV1ZrbDZZ VVJPVmsxR1NsTmFSM2hMVjBVeFYxSnJOVmRTYkc4d1ZrUkdiMUl5VmtoVmJGWlhZa1UxV1ZsclZuWmxiRkpWVTJwQ2FHRjZi RmhXTVZKUFZHMVdjbU5FVGxWaGF6VXpXVlZWTVU1c1JuUmxSbWhVVWpOb01GZHNWbGRXTVZKelZHNVNUbFpyV2xkVVYzaFhU bXhSZUZScVFsTldNVXBXVlRJeGIyRXlTa2hWYm5CaFZucFdNMVJWV2t0ak1WcDFZMGQwVTAxWVFqSldiWFJoVXpGU1YySklR bEJYUlVwWVZteFNRbVZXVm5KWk0yUk9WbFJXZDFReFpFZFdWbHBJWVVWb1dHSllRbWhaZWtGNFVqSktSMVZzVWxOTlYzUXpW MVJHVjAxSFNrZFZhMlJXVmtVMVQxbFhkSEpOVmxweFVXMDViR0pHV2tsYVZXaFhWV3N4Vm1FemNGWmlXR2g1V2tjeFIxSnJP VmxoUlRWVFlURldORmRzWTNoVmF6RnpVbGhzVkdKcldsZFVWM0JTWkRGV1ZWSnJUazlTTVZwV1ZsYzFWMVl4U2paU2JIQmhV bXhLU0ZVd1drdFRSMDVGVm1zNVRsWXhTa1pXUmxKSFl6RktTRlpyVmxkaE0yaG9WbXhrVGsxV1VuTlhiWFJUVFZoQ1IxcFZh RTlVVlRGMFlVaEdXazB6UW1GWk1uTjRVakpLU0dSRk5VNWlWa3BhVmxkd1IxWXhSWGxUYTJSWVlrVktZVlpzWkc5alZsWlpZ MGQwVjFKcmNGcFpNR1J2VlRGWmVHTkljRmRXYkZwVVZteGFXbVF3T1ZoaVJUbFhZVEk0ZVZaRlVrZFVNazE1VTJ0b1VGWjZS bkZXYWs1clRteHdSMXBHVG10aVZUVXdXbFZrTkdGR1dYaFdXR1JhVm0xb1UxUnJaRXRXTVdSWllVVTFWRkpyYTNkWFYzUlhV MnMxUjJKSVVsWmliV2hUV1ZSR2QyVldXbGRXVkZaVVVteEdObFZ0Y0V0WFJrbzJWbXhXVm1KWVFtaFdSbVJHWlZkT1JtTkhh RmRpV0doTlYxZDBVMVl4VFhkTlZtaFZWMGhDY0Zsc1ZYaE9WbkJJWkVkMFYwMXJOVmxXUnpWelZVWlplbGt6YUZkaVdGSnlX V3BHYTFOR1ZuTmlSbkJPWWxaS1JsWlVUbmRpYlZGNFkwaEtWMkpZYUZWWlYzaDNZakZTYzFwRlpHeFdiRm94VlRJd2VGZHNX bkpYYmxKaFVsWktWRmxXWkV0VFZtUnlWRzE0VTFKWVFYbFhWM2hUVlRGc1YxTnVTazVUU0VKV1ZGUkJNV1ZzY0VsaGVsWnFW bXMxVjFZeWRHOVVNa3AwVkdwT1ZsWkZXbGhXUlZwSFYxZEtTVlJzVms1V01ERTBWbXRXYTFKdFVuTlZhMXBvVFRKb1ZsUlda RFJTYkZKeFUycENWVkpyV2xsV2JURnpWbFpLU0dRelpGZGlSbG96VmxWa1QyTldSbkpPVmxaVFZsaEJNbFpHVm1wa01EVkhV MjVLVm1KRk5VNVVWV2hPWkRGa1YyRkdUbWxpUlhCSFZrY3hkMVl5Vm5KWGFscGFWbTFvZGxZd1ZYaFdWbVJaVTIxNGFFMXNT akpXVm1NeFYyc3hkRlZZYkdGbGJGcHhXV3RXZDFWc1VsZGhSbVJQWWxaS1dsVXllR0ZoYkZsNldUTnNZVk5JUWxoV1JtUkhW a2RTU1dKRk5WZFdiVGswVm14a2NrNVdaRWhUYkZacFVrVktUMVpxUm1Gak1XeFdZVVYwYTJGNlFqVlhWRTV2VlRBeFNHRkZV bFpoTW1oWVdWWmFZVll4YjNwaFJrSlRWbXR3TWxaRVJtdFZNVXB6VW01R1VtSnNTbkZWYWs1dlZERmFSVlJ1VGxkaVJUVkhX a1ZTUjFSdFJYZE9WMmhoVW5wR2RsUldXa2RXYkdSMVVXczVUbUpGYjNsV01uaE9UbFpTZEZSclZsVmlWR3h6Vm0weE5FMXNX blZqUldSVllraENWMXBWV25kWGF6RnpZMGM1V21FeWFIbFVWbVJUVjBaYWRXSkdUbWxpUm5CaFYxUkNiMVV4U2taT1ZXeFlZ VEpvWVZsc1ZsZE9WazQyVTJwT2FtSkdTbnBWTW5CTFZHeGtSMU5zYUZwV1YyaFlWVEJWTVZKdFZrZGpSVGxvVFVad1MxWXlk Rk5pTVU1WFlrWldWMkZyU2xoWmJYaGhVa1prV0dWSGRHaGlSbTh5VlRKNFYxVnRSbkpUYlVaWFRWZG9URlpIZUd0V1ZsWnpX a1U1YVZaSGVFVlhWRUpoVWpGc1YyTklUbWhTTUZwWFdXdFdZVTVXV2tobFIzUlZWakF4TlZZeWNGTldiR1JHWVROb1drMVhh SHBYVm1ST1pWZFdSbHBIY0U1TmFtdDVWakZhYTJFeFNuSk9XRTVXVjBkU2NGWnNVbkpOUm10M1ZXeHdiRlpyTVRaVmJYUmhW bXhhU0dWRVdscGhhMGwzV1RCa1UyTXhUblZqUmxaVVVtdHdNRmRYZEc5ak1WbDVWV3RrYUZKWGFITlZha0V4V1ZaU2RHVkZU azlpUlZwV1ZsZHdRMVF5Vm5OWGJXaGFWak5vTTFZeWVIZFRSVGxZWVVkb1UxSlZjRlJXTW5oaFVqQXhWMVJzVmxSaWJrSlFW bXBDY21Wc1drZGFSV1JhVm14R00xVnRlRU5XYkVwVlVtcFNWMVpXU25wYVZ6RlRVbXN4VmxOdGRFNU5iRXBvVmpKNFQyVnRW blJXYkd4U1lUQndXRmxyWkc5TmJGRjRWV3M1VTFaVVZrWldNblJYV1ZkS2NsZHJiRmRoYXpWUVdXdGFVMk5XV25KaFJtUnBV bXh3U1ZZeFVrdFRNa3BHVGtob1lWSXdXbkZaYlRGdlRsWmFkV05GT1ZoV2F6VkpWMnRhYjFkR1NraGFTR3hXWVd0S2NsWkVT bE5UUlRWWFUyeFNVMDF1VGpaWFYzaFhWbTFXU0ZScVdtRlRSVXB4V1Zod2MxSnNWblJOVlRsVFRWWndNVlZYZERCVk1WbDVW V3hhVmsxSFVYcFVWbHBQVW14V2NWZHJOVk5pYTBvMlZteGFZVk14WkVoVmEyeFdZWHBzY1ZsdE1UUlZiRkpXV2taa1RtRjZS a2haVlZWNFlWWlplbHBFVWxoaGF6VlFXVlphVm1ReVZrVlViSEJZVWpOUmVsZFdaRFJXTWxGM1l6TmthMUpHU205V2JGWmhU bFpWZDJGSVpGVldWRVpJVm0weGMyRXhXWGhYYWtKWFlURmFWRlpzV21GWFZtUnpWRzEwYUUweWFFUldiWEJQVlRKTmVHTklV bFppYXpWb1ZXeFdZVlpHY0ZaWGJHUnBWbXR3TUZVeWNFOVViR1JKVVc1c1ZXRXhXbFJhVmxwclpFWldkRkpzVGxOaVIzUTBW MVpXYjFReVRYZE9WV1JTWWtWd2NsVnRkSFpsUm5CSVpFaE9WVkl4V2xsYVJXaEhWVEF4YzFOdVdsaFdSVFZ5VmtkNGMxZEdj RVpsUjNob1RURkpNRmRyVWt0ak1rVjRVMnhvWVdWc1NsZFZhMXBoWTJ4U2NWTnFRbFppUmxZMVdWVm9iMkZWTVVkalJscGFZ VEZhV0ZaVVJsTmtSVGxKWVVab2FHRXpRbUZXVkVwM1VURkdkRkp1VGxKaGF6VnpWbXRWTVdOV1dYbGxSVGxYVm14V05sWXlj RWRVUlRGWFZsaGtWV0pZVFhoYVYzaGFaVVpXY1ZOc1VrNWlWMmhRVjFaV1UxTnRWblJUYkZaVFZrVndjVmx0TVhwa01WSnhW RzA1YUUxVk5VbFdNbkJEWVZaYVdWRnFWbFpOUjAweFZURlZlRk5YUmtobFJUbFVVbGhDZWxacVNURmtNVnBIVW01U2FGSkdT bFJWYkZKU1RWWldWVkZ0UmxkTlZUVXdWa2MxUjFaR1dsZFRha1poVWtWd2VsUlhlRnBrTVdSMVUyeG9hVlpHUmpSWGJHTXhW akZGZUZSc1pHaFNiRXBRVkZkd2MxSXhXblJsUlhSV1RWVndWbGxyV210V1ZURkpXVE5zVmsxcVJuWmFWVlY0VWxaU2RWZHRl Rk5YUlRReVZrUkNZVlF3TlhOV2JHaFVZV3RLVkZsdE1UUlJNV1JYVjJ4T1UxSnRkRE5XTWpWTFlURmFTR1I2U2xwaVdGSkxW RlZWTVZOWFNqWldhemxvVjBaS1RsZHNWbGRrTVZGNVZHdHNWbFpGY0U5V2JGcGhVa1pSZUdGSGRHbE5WbHA0Vm0xNFUxVXdN VVpXYWxwVlZqTlNlbFpxU2xOa1ZrNTBaRWRzVGxZelp6RldSRUpxVGxVeFdGTnFXbWhUUlVwVVdXeGtVazFHWkZobFNFcE9U VlZ3VjFVeFVrdFZiRmw1WlVSV1lWSnNXVEJVYlRGVFZtczVSVkZzVms1WFJVcEtWa1pqTVdJeVRrZGlSbFpVWVROU1dWVnJX bk5PUmxsM1YyeGtWV0pWY0RCVmJGSlhZVEZLYzJORk9WWmlXRTEzVkZWYWRtVlhTWHBpUmtKVFRUQkpNbFpFUm10T1IwMTRW R3RvVTJKR1duSmFWM2hLVFVaYWNscEVVbEppUmxwWFZHeFNUMkV4V2tkalNHaFZWak5DY1ZSWGVGcGxSa1p4Vm1zNVYySkZj RlZYYTJSM1dWWlJlRmRzYkdwVFIzaFlXVlJLYjJWR1VYaFhiWFJVVW01Q1NWWkdhSE5YUms1SVZXcEdWMVpGV2xOVVZXUkxZ ekpLUjJKSGJGZFNiRlY0VmpJeE1GbFZNWFJUYTJob1VsWmFVRmxVUVRGT1JtUnlXa1pPYTJKR2NIcFdNbk40VlVaYVIxWnFW bGhoTW1oRVdXcEdWMlJGTlZkYVIyeFlVakF4TlZkWGRHRlVNazVIVkd0c1YyRjZSbFJXYTFVeFpGWlNXRTVXVGxoV2JHdzFW RlZvZDJGc1duTmpSbEpZWVdzMWNsUnJXbFpsVmxaeVkwWlNiRlpIZUVoV2JURXdWakpLV0ZKcldtcFNiRXBSVld4YWQxSnNV bk5hUlhST1VtNUNWMWxyYUVOV1ZscFdWMjFHVjAxWFVqSlVhMXBPWlZkU1IxUnNUbGhTYkZWNFZtMTRiMUV4V25OalJWWldZ V3hLVlZWcVJsWk5SbHBYV2taa1YwMXNXa2RWYlRWRFZFVXhSVlZxV2xkTmFsWjJXWHBLUjFOSFZrWlZiRlpYVFdzMU5WZHJV azlUTVZwSFZWaHNWR0p0ZUZsV1ZFNVRVa1prV0dORlRrNVNiVko1V2tod1ExZEdTbk5XYWs1V1lXdHdhRmxXVlhkbGJIQkpW RzFzVGxaWE9UUldNV1IzVVRGV2MySXpiRkJXYXpWUFZtcEJNVmxXYkZkWGEzUlZUVVJzU0ZZeWRHdFVhekYwWVVVeFZWWXph RkJhVmxwelYwWmtjMkpIZUdsV1JWcFNWMVJHVjJNeFJuTlVhMnhvVWpOQ2FGbFVUa05UUm14VlUyNWtiRll3TVRWVk1uQlBW VzFLUm1JelpGcGhhelY2VmpGV2VtVkdaRlZUYkdSWFlsWktNbGRYZEZkaU1VcEhWV3hvYWxJelFtRldiRkpUVGxaa2RFNVdU bXRTYmtKR1ZtMXpNVlpyTVhOWGJrSlhVbTFSZWxScldtRmtWbEoxWTBaU2JHSkZhM2xXVkVaWFZHMVdWMVJyYkZKWFIyaFlW V3hvVTFkV1VuSldiR1JPWWtkME5sWlhjRWRWYlVwSVZWUktWMkpVUlhkWFZtUlBUbXhhV1ZwR1VsTmlWa3BFVlROd1MyUXhU blJTYWxwVlYwVndVVlp0ZUdGV2JGcHlZVVprYUZJd1drWlZNalZyVmpKS2MxZHFWbGRoYXpWUVdUSXhUMUpzY0RaU2JYUllV bFZ3Tmxkc1ZrNU9Wa3BJVWxoc1ZXSkdjSEJaYlRGclRXeGFWVk5yWkZoU2JYUXpWVEZTVTFWR1NrWlRiRVphVFVad1dGVnFT bGRTVmxKelUyeG9XRkl4U25sV01WcFRZakZLY2s1SWJGUmhhMHBVVkZab1EyRkdVbFpXVkVab1VqRmFWMWxyYUhOV1YwcElZ VVJTVjAxcVJrZGFWVnAzWTJ4a2NsVnNVbE5XUjNoV1ZsZDBiMWxWTlVkYVNFcFFWbGRTY2xaVVRsTmxiRlYzVjJ0YWJGWnVR bFpYYTFZMFZqRktjMWRxVmxoV2VrSTBXV3RWZUdOV1ZsbFRiWFJYVmtkNFdsWnJVazlrTWxKR1l6TnNhVkp0VWxWVk1GVjNa VVp3U0dORlpHcFNNRm93Vm0weFIyRkhTblJoU0VwV1lrWndUMXBXV2tkV1ZsSnlZVVpTYVZKcmIzZFdSbU40WkdzeFIxUnJh R2hTVm5CUFZXcE9RMk5XVlhsT1ZXUlNUVVJHTVZkclVsTlZhekZHVFVSQ1YySlVRalJWZWtwVFpGWldkVlZzVWxkU00yaFJW MWh3VDJOck1IZE9WV3hWWWxSV1YxWnJXa3RrTVhCV1dYcFdUbUpGY0VoWGEyaERWbXhLTmxKck1WUmxhMFV4V1ZWVmVFNVZP VlpXYkdST1lXdGFiMVpYZUc5aU1VbDVVbTVXVm1Kc2NGTlVWRW96VFd4V1dFMUVSbWhTYXpFelZtMTRRMVZHV2xaT1dGWlZW bXh3UjFwSGN6RlRWbkJIVTJzNVRsWlVWbGhXVmxKTFltMVdkRkp1VGxKaVIyaHhWbXhTYzFKR1ZuUmpSazVZWWtoQ1dGZFlj RU5oTWtwSFkwVndWMkV5VWpOV01WcExaRVpPVlZOc1dteFdSM2N3VmxjeE1GSnJNSGhTV0doVllXczFXVlpzYUc5WFJuQllU VmRHVkUxV1drcFdNalZEVkd4S1NGVnJPV0ZXYldoeVZsWldlbVZHVW5SaVIyeFhZbGRvU1Zkc1pEQlNNRFZJVld4b1ZHSnVR bFZWYWs1U1pXeGtWVlJ1VGxWV2JYaGFWbTF6TVZaWFNsaFZiV2hhWWtkb1RGWkVSbUZTTWtaRlZXczVWRkpVVm5aV01qRTBV ekpOZVZSWWFGTmliV2h5V1cxMFMxUXhaRmRaTTJScVlYcENOVmRxVG5kV2JGcEhVMjVPVlUxWFVsaFpNRnBUVTBVNVZrMVdV bE5OYlZFeFZteGFiMWxXWkhOU2JGWmhUVEo0VDFaclpGTmxiRkp6Vlc1S1RrMVZjSHBYYTFwWFZGZFdkR1ZJVGxoaE1VcHlW akJWZDJWV1pIUmpSM1JwVWpKb2FGZHJaRFJSTWxaWVZXcFdVRkpGTlU5WmJURlRUa1pTVjFScVFsZFdiRnBHV1ZWV1QxbFZN WEpXVkVKWVlsUkZkMVZVU2xkVFZrcHlWV3N4VGsxc1NrUldWVnBQVTIxT1JtUkdVbWhsYlU1d1V6Rk9jazR3YkVWUFEzTnBT MU5yTjBsRU9Dc2lLU2s3SUQ4KyIpKTsgPz4=")); ?>src/Exception/Http/Status501.php000064400000000725150211046430012432 0ustar00code = (int) $data->status_code; } parent::__construct($reason, $data); } } src/Exception/Http/Status418.php000064400000001054150211046430012435 0ustar00 FF01:0:0:0:0:0:0:101 * ::1 -> 0:0:0:0:0:0:0:1 * * @author Alexander Merz * @author elfrink at introweb dot nl * @author Josh Peck * @copyright 2003-2005 The PHP Group * @license https://opensource.org/licenses/bsd-license.php * * @param string|Stringable $ip An IPv6 address * @return string The uncompressed IPv6 address * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string or a stringable object. */ public static function uncompress($ip) { if (InputValidator::is_string_or_stringable($ip) === false) { throw InvalidArgument::create(1, '$ip', 'string|Stringable', gettype($ip)); } $ip = (string) $ip; if (substr_count($ip, '::') !== 1) { return $ip; } list($ip1, $ip2) = explode('::', $ip); $c1 = ($ip1 === '') ? -1 : substr_count($ip1, ':'); $c2 = ($ip2 === '') ? -1 : substr_count($ip2, ':'); if (strpos($ip2, '.') !== false) { $c2++; } if ($c1 === -1 && $c2 === -1) { // :: $ip = '0:0:0:0:0:0:0:0'; } elseif ($c1 === -1) { // ::xxx $fill = str_repeat('0:', 7 - $c2); $ip = str_replace('::', $fill, $ip); } elseif ($c2 === -1) { // xxx:: $fill = str_repeat(':0', 7 - $c1); $ip = str_replace('::', $fill, $ip); } else { // xxx::xxx $fill = ':' . str_repeat('0:', 6 - $c2 - $c1); $ip = str_replace('::', $fill, $ip); } return $ip; } /** * Compresses an IPv6 address * * RFC 4291 allows you to compress consecutive zero pieces in an address to * '::'. This method expects a valid IPv6 address and compresses consecutive * zero pieces to '::'. * * Example: FF01:0:0:0:0:0:0:101 -> FF01::101 * 0:0:0:0:0:0:0:1 -> ::1 * * @see \WpOrg\Requests\Ipv6::uncompress() * * @param string $ip An IPv6 address * @return string The compressed IPv6 address */ public static function compress($ip) { // Prepare the IP to be compressed. // Note: Input validation is handled in the `uncompress()` method, which is the first call made in this method. $ip = self::uncompress($ip); $ip_parts = self::split_v6_v4($ip); // Replace all leading zeros $ip_parts[0] = preg_replace('/(^|:)0+([0-9])/', '\1\2', $ip_parts[0]); // Find bunches of zeros if (preg_match_all('/(?:^|:)(?:0(?::|$))+/', $ip_parts[0], $matches, PREG_OFFSET_CAPTURE)) { $max = 0; $pos = null; foreach ($matches[0] as $match) { if (strlen($match[0]) > $max) { $max = strlen($match[0]); $pos = $match[1]; } } $ip_parts[0] = substr_replace($ip_parts[0], '::', $pos, $max); } if ($ip_parts[1] !== '') { return implode(':', $ip_parts); } else { return $ip_parts[0]; } } /** * Splits an IPv6 address into the IPv6 and IPv4 representation parts * * RFC 4291 allows you to represent the last two parts of an IPv6 address * using the standard IPv4 representation * * Example: 0:0:0:0:0:0:13.1.68.3 * 0:0:0:0:0:FFFF:129.144.52.38 * * @param string $ip An IPv6 address * @return string[] [0] contains the IPv6 represented part, and [1] the IPv4 represented part */ private static function split_v6_v4($ip) { if (strpos($ip, '.') !== false) { $pos = strrpos($ip, ':'); $ipv6_part = substr($ip, 0, $pos); $ipv4_part = substr($ip, $pos + 1); return [$ipv6_part, $ipv4_part]; } else { return [$ip, '']; } } /** * Checks an IPv6 address * * Checks if the given IP is a valid IPv6 address * * @param string $ip An IPv6 address * @return bool true if $ip is a valid IPv6 address */ public static function check_ipv6($ip) { // Note: Input validation is handled in the `uncompress()` method, which is the first call made in this method. $ip = self::uncompress($ip); list($ipv6, $ipv4) = self::split_v6_v4($ip); $ipv6 = explode(':', $ipv6); $ipv4 = explode('.', $ipv4); if (count($ipv6) === 8 && count($ipv4) === 1 || count($ipv6) === 6 && count($ipv4) === 4) { foreach ($ipv6 as $ipv6_part) { // The section can't be empty if ($ipv6_part === '') { return false; } // Nor can it be over four characters if (strlen($ipv6_part) > 4) { return false; } // Remove leading zeros (this is safe because of the above) $ipv6_part = ltrim($ipv6_part, '0'); if ($ipv6_part === '') { $ipv6_part = '0'; } // Check the value is valid $value = hexdec($ipv6_part); if (dechex($value) !== strtolower($ipv6_part) || $value < 0 || $value > 0xFFFF) { return false; } } if (count($ipv4) === 4) { foreach ($ipv4 as $ipv4_part) { $value = (int) $ipv4_part; if ((string) $value !== $ipv4_part || $value < 0 || $value > 0xFF) { return false; } } } return true; } else { return false; } } } src/Auth.php000064400000001534150211046430006744 0ustar00 '\WpOrg\Requests\Auth', 'requests_hooker' => '\WpOrg\Requests\HookManager', 'requests_proxy' => '\WpOrg\Requests\Proxy', 'requests_transport' => '\WpOrg\Requests\Transport', // Classes. 'requests_cookie' => '\WpOrg\Requests\Cookie', 'requests_exception' => '\WpOrg\Requests\Exception', 'requests_hooks' => '\WpOrg\Requests\Hooks', 'requests_idnaencoder' => '\WpOrg\Requests\IdnaEncoder', 'requests_ipv6' => '\WpOrg\Requests\Ipv6', 'requests_iri' => '\WpOrg\Requests\Iri', 'requests_response' => '\WpOrg\Requests\Response', 'requests_session' => '\WpOrg\Requests\Session', 'requests_ssl' => '\WpOrg\Requests\Ssl', 'requests_auth_basic' => '\WpOrg\Requests\Auth\Basic', 'requests_cookie_jar' => '\WpOrg\Requests\Cookie\Jar', 'requests_proxy_http' => '\WpOrg\Requests\Proxy\Http', 'requests_response_headers' => '\WpOrg\Requests\Response\Headers', 'requests_transport_curl' => '\WpOrg\Requests\Transport\Curl', 'requests_transport_fsockopen' => '\WpOrg\Requests\Transport\Fsockopen', 'requests_utility_caseinsensitivedictionary' => '\WpOrg\Requests\Utility\CaseInsensitiveDictionary', 'requests_utility_filterediterator' => '\WpOrg\Requests\Utility\FilteredIterator', 'requests_exception_http' => '\WpOrg\Requests\Exception\Http', 'requests_exception_transport' => '\WpOrg\Requests\Exception\Transport', 'requests_exception_transport_curl' => '\WpOrg\Requests\Exception\Transport\Curl', 'requests_exception_http_304' => '\WpOrg\Requests\Exception\Http\Status304', 'requests_exception_http_305' => '\WpOrg\Requests\Exception\Http\Status305', 'requests_exception_http_306' => '\WpOrg\Requests\Exception\Http\Status306', 'requests_exception_http_400' => '\WpOrg\Requests\Exception\Http\Status400', 'requests_exception_http_401' => '\WpOrg\Requests\Exception\Http\Status401', 'requests_exception_http_402' => '\WpOrg\Requests\Exception\Http\Status402', 'requests_exception_http_403' => '\WpOrg\Requests\Exception\Http\Status403', 'requests_exception_http_404' => '\WpOrg\Requests\Exception\Http\Status404', 'requests_exception_http_405' => '\WpOrg\Requests\Exception\Http\Status405', 'requests_exception_http_406' => '\WpOrg\Requests\Exception\Http\Status406', 'requests_exception_http_407' => '\WpOrg\Requests\Exception\Http\Status407', 'requests_exception_http_408' => '\WpOrg\Requests\Exception\Http\Status408', 'requests_exception_http_409' => '\WpOrg\Requests\Exception\Http\Status409', 'requests_exception_http_410' => '\WpOrg\Requests\Exception\Http\Status410', 'requests_exception_http_411' => '\WpOrg\Requests\Exception\Http\Status411', 'requests_exception_http_412' => '\WpOrg\Requests\Exception\Http\Status412', 'requests_exception_http_413' => '\WpOrg\Requests\Exception\Http\Status413', 'requests_exception_http_414' => '\WpOrg\Requests\Exception\Http\Status414', 'requests_exception_http_415' => '\WpOrg\Requests\Exception\Http\Status415', 'requests_exception_http_416' => '\WpOrg\Requests\Exception\Http\Status416', 'requests_exception_http_417' => '\WpOrg\Requests\Exception\Http\Status417', 'requests_exception_http_418' => '\WpOrg\Requests\Exception\Http\Status418', 'requests_exception_http_428' => '\WpOrg\Requests\Exception\Http\Status428', 'requests_exception_http_429' => '\WpOrg\Requests\Exception\Http\Status429', 'requests_exception_http_431' => '\WpOrg\Requests\Exception\Http\Status431', 'requests_exception_http_500' => '\WpOrg\Requests\Exception\Http\Status500', 'requests_exception_http_501' => '\WpOrg\Requests\Exception\Http\Status501', 'requests_exception_http_502' => '\WpOrg\Requests\Exception\Http\Status502', 'requests_exception_http_503' => '\WpOrg\Requests\Exception\Http\Status503', 'requests_exception_http_504' => '\WpOrg\Requests\Exception\Http\Status504', 'requests_exception_http_505' => '\WpOrg\Requests\Exception\Http\Status505', 'requests_exception_http_511' => '\WpOrg\Requests\Exception\Http\Status511', 'requests_exception_http_unknown' => '\WpOrg\Requests\Exception\Http\StatusUnknown', ]; /** * Register the autoloader. * * Note: the autoloader is *prepended* in the autoload queue. * This is done to ensure that the Requests 2.0 autoloader takes precedence * over a potentially (dependency-registered) Requests 1.x autoloader. * * @internal This method contains a safeguard against the autoloader being * registered multiple times. This safeguard uses a global constant to * (hopefully/in most cases) still function correctly, even if the * class would be renamed. * * @return void */ public static function register() { if (defined('REQUESTS_AUTOLOAD_REGISTERED') === false) { spl_autoload_register([self::class, 'load'], true); define('REQUESTS_AUTOLOAD_REGISTERED', true); } } /** * Autoloader. * * @param string $class_name Name of the class name to load. * * @return bool Whether a class was loaded or not. */ public static function load($class_name) { // Check that the class starts with "Requests" (PSR-0) or "WpOrg\Requests" (PSR-4). $psr_4_prefix_pos = strpos($class_name, 'WpOrg\\Requests\\'); if (stripos($class_name, 'Requests') !== 0 && $psr_4_prefix_pos !== 0) { return false; } $class_lower = strtolower($class_name); if ($class_lower === 'requests') { // Reference to the original PSR-0 Requests class. $file = dirname(__DIR__) . '/library/Requests.php'; } elseif ($psr_4_prefix_pos === 0) { // PSR-4 classname. $file = __DIR__ . '/' . strtr(substr($class_name, 15), '\\', '/') . '.php'; } if (isset($file) && file_exists($file)) { include $file; return true; } /* * Okay, so the class starts with "Requests", but we couldn't find the file. * If this is one of the deprecated/renamed PSR-0 classes being requested, * let's alias it to the new name and throw a deprecation notice. */ if (isset(self::$deprecated_classes[$class_lower])) { /* * Integrators who cannot yet upgrade to the PSR-4 class names can silence deprecations * by defining a `REQUESTS_SILENCE_PSR0_DEPRECATIONS` constant and setting it to `true`. * The constant needs to be defined before the first deprecated class is requested * via this autoloader. */ if (!defined('REQUESTS_SILENCE_PSR0_DEPRECATIONS') || REQUESTS_SILENCE_PSR0_DEPRECATIONS !== true) { // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error trigger_error( 'The PSR-0 `Requests_...` class names in the Requests library are deprecated.' . ' Switch to the PSR-4 `WpOrg\Requests\...` class names at your earliest convenience.', E_USER_DEPRECATED ); // Prevent the deprecation notice from being thrown twice. if (!defined('REQUESTS_SILENCE_PSR0_DEPRECATIONS')) { define('REQUESTS_SILENCE_PSR0_DEPRECATIONS', true); } } // Create an alias and let the autoloader recursively kick in to load the PSR-4 class. return class_alias(self::$deprecated_classes[$class_lower], $class_name, true); } return false; } } } src/Exception.php000064400000002132150211046430007774 0ustar00type = $type; $this->data = $data; } /** * Like {@see \Exception::getCode()}, but a string code. * * @codeCoverageIgnore * @return string */ public function getType() { return $this->type; } /** * Gives any relevant data * * @codeCoverageIgnore * @return mixed */ public function getData() { return $this->data; } } src/Capability.php000064400000001214150211046430010117 0ustar00 array( 'port' => Port::ACAP, ), 'dict' => array( 'port' => Port::DICT, ), 'file' => array( 'ihost' => 'localhost', ), 'http' => array( 'port' => Port::HTTP, ), 'https' => array( 'port' => Port::HTTPS, ), ); /** * Return the entire IRI when you try and read the object as a string * * @return string */ public function __toString() { return $this->get_iri(); } /** * Overload __set() to provide access via properties * * @param string $name Property name * @param mixed $value Property value */ public function __set($name, $value) { if (method_exists($this, 'set_' . $name)) { call_user_func(array($this, 'set_' . $name), $value); } elseif ( $name === 'iauthority' || $name === 'iuserinfo' || $name === 'ihost' || $name === 'ipath' || $name === 'iquery' || $name === 'ifragment' ) { call_user_func(array($this, 'set_' . substr($name, 1)), $value); } } /** * Overload __get() to provide access via properties * * @param string $name Property name * @return mixed */ public function __get($name) { // isset() returns false for null, we don't want to do that // Also why we use array_key_exists below instead of isset() $props = get_object_vars($this); if ( $name === 'iri' || $name === 'uri' || $name === 'iauthority' || $name === 'authority' ) { $method = 'get_' . $name; $return = $this->$method(); } elseif (array_key_exists($name, $props)) { $return = $this->$name; } // host -> ihost elseif (($prop = 'i' . $name) && array_key_exists($prop, $props)) { $name = $prop; $return = $this->$prop; } // ischeme -> scheme elseif (($prop = substr($name, 1)) && array_key_exists($prop, $props)) { $name = $prop; $return = $this->$prop; } else { trigger_error('Undefined property: ' . get_class($this) . '::' . $name, E_USER_NOTICE); $return = null; } if ($return === null && isset($this->normalization[$this->scheme][$name])) { return $this->normalization[$this->scheme][$name]; } else { return $return; } } /** * Overload __isset() to provide access via properties * * @param string $name Property name * @return bool */ public function __isset($name) { return (method_exists($this, 'get_' . $name) || isset($this->$name)); } /** * Overload __unset() to provide access via properties * * @param string $name Property name */ public function __unset($name) { if (method_exists($this, 'set_' . $name)) { call_user_func(array($this, 'set_' . $name), ''); } } /** * Create a new IRI object, from a specified string * * @param string|Stringable|null $iri * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $iri argument is not a string, Stringable or null. */ public function __construct($iri = null) { if ($iri !== null && InputValidator::is_string_or_stringable($iri) === false) { throw InvalidArgument::create(1, '$iri', 'string|Stringable|null', gettype($iri)); } $this->set_iri($iri); } /** * Create a new IRI object by resolving a relative IRI * * Returns false if $base is not absolute, otherwise an IRI. * * @param \WpOrg\Requests\Iri|string $base (Absolute) Base IRI * @param \WpOrg\Requests\Iri|string $relative Relative IRI * @return \WpOrg\Requests\Iri|false */ public static function absolutize($base, $relative) { if (!($relative instanceof self)) { $relative = new self($relative); } if (!$relative->is_valid()) { return false; } elseif ($relative->scheme !== null) { return clone $relative; } if (!($base instanceof self)) { $base = new self($base); } if ($base->scheme === null || !$base->is_valid()) { return false; } if ($relative->get_iri() !== '') { if ($relative->iuserinfo !== null || $relative->ihost !== null || $relative->port !== null) { $target = clone $relative; $target->scheme = $base->scheme; } else { $target = new self; $target->scheme = $base->scheme; $target->iuserinfo = $base->iuserinfo; $target->ihost = $base->ihost; $target->port = $base->port; if ($relative->ipath !== '') { if ($relative->ipath[0] === '/') { $target->ipath = $relative->ipath; } elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === '') { $target->ipath = '/' . $relative->ipath; } elseif (($last_segment = strrpos($base->ipath, '/')) !== false) { $target->ipath = substr($base->ipath, 0, $last_segment + 1) . $relative->ipath; } else { $target->ipath = $relative->ipath; } $target->ipath = $target->remove_dot_segments($target->ipath); $target->iquery = $relative->iquery; } else { $target->ipath = $base->ipath; if ($relative->iquery !== null) { $target->iquery = $relative->iquery; } elseif ($base->iquery !== null) { $target->iquery = $base->iquery; } } $target->ifragment = $relative->ifragment; } } else { $target = clone $base; $target->ifragment = null; } $target->scheme_normalization(); return $target; } /** * Parse an IRI into scheme/authority/path/query/fragment segments * * @param string $iri * @return array */ protected function parse_iri($iri) { $iri = trim($iri, "\x20\x09\x0A\x0C\x0D"); $has_match = preg_match('/^((?P[^:\/?#]+):)?(\/\/(?P[^\/?#]*))?(?P[^?#]*)(\?(?P[^#]*))?(#(?P.*))?$/', $iri, $match); if (!$has_match) { throw new Exception('Cannot parse supplied IRI', 'iri.cannot_parse', $iri); } if ($match[1] === '') { $match['scheme'] = null; } if (!isset($match[3]) || $match[3] === '') { $match['authority'] = null; } if (!isset($match[5])) { $match['path'] = ''; } if (!isset($match[6]) || $match[6] === '') { $match['query'] = null; } if (!isset($match[8]) || $match[8] === '') { $match['fragment'] = null; } return $match; } /** * Remove dot segments from a path * * @param string $input * @return string */ protected function remove_dot_segments($input) { $output = ''; while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..') { // A: If the input buffer begins with a prefix of "../" or "./", // then remove that prefix from the input buffer; otherwise, if (strpos($input, '../') === 0) { $input = substr($input, 3); } elseif (strpos($input, './') === 0) { $input = substr($input, 2); } // B: if the input buffer begins with a prefix of "/./" or "/.", // where "." is a complete path segment, then replace that prefix // with "/" in the input buffer; otherwise, elseif (strpos($input, '/./') === 0) { $input = substr($input, 2); } elseif ($input === '/.') { $input = '/'; } // C: if the input buffer begins with a prefix of "/../" or "/..", // where ".." is a complete path segment, then replace that prefix // with "/" in the input buffer and remove the last segment and its // preceding "/" (if any) from the output buffer; otherwise, elseif (strpos($input, '/../') === 0) { $input = substr($input, 3); $output = substr_replace($output, '', (strrpos($output, '/') ?: 0)); } elseif ($input === '/..') { $input = '/'; $output = substr_replace($output, '', (strrpos($output, '/') ?: 0)); } // D: if the input buffer consists only of "." or "..", then remove // that from the input buffer; otherwise, elseif ($input === '.' || $input === '..') { $input = ''; } // E: move the first path segment in the input buffer to the end of // the output buffer, including the initial "/" character (if any) // and any subsequent characters up to, but not including, the next // "/" character or the end of the input buffer elseif (($pos = strpos($input, '/', 1)) !== false) { $output .= substr($input, 0, $pos); $input = substr_replace($input, '', 0, $pos); } else { $output .= $input; $input = ''; } } return $output . $input; } /** * Replace invalid character with percent encoding * * @param string $text Input string * @param string $extra_chars Valid characters not in iunreserved or * iprivate (this is ASCII-only) * @param bool $iprivate Allow iprivate * @return string */ protected function replace_invalid_with_pct_encoding($text, $extra_chars, $iprivate = false) { // Normalize as many pct-encoded sections as possible $text = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array($this, 'remove_iunreserved_percent_encoded'), $text); // Replace invalid percent characters $text = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $text); // Add unreserved and % to $extra_chars (the latter is safe because all // pct-encoded sections are now valid). $extra_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%'; // Now replace any bytes that aren't allowed with their pct-encoded versions $position = 0; $strlen = strlen($text); while (($position += strspn($text, $extra_chars, $position)) < $strlen) { $value = ord($text[$position]); // Start position $start = $position; // By default we are valid $valid = true; // No one byte sequences are valid due to the while. // Two byte sequence: if (($value & 0xE0) === 0xC0) { $character = ($value & 0x1F) << 6; $length = 2; $remaining = 1; } // Three byte sequence: elseif (($value & 0xF0) === 0xE0) { $character = ($value & 0x0F) << 12; $length = 3; $remaining = 2; } // Four byte sequence: elseif (($value & 0xF8) === 0xF0) { $character = ($value & 0x07) << 18; $length = 4; $remaining = 3; } // Invalid byte: else { $valid = false; $length = 1; $remaining = 0; } if ($remaining) { if ($position + $length <= $strlen) { for ($position++; $remaining; $position++) { $value = ord($text[$position]); // Check that the byte is valid, then add it to the character: if (($value & 0xC0) === 0x80) { $character |= ($value & 0x3F) << (--$remaining * 6); } // If it is invalid, count the sequence as invalid and reprocess the current byte: else { $valid = false; $position--; break; } } } else { $position = $strlen - 1; $valid = false; } } // Percent encode anything invalid or not in ucschar if ( // Invalid sequences !$valid // Non-shortest form sequences are invalid || $length > 1 && $character <= 0x7F || $length > 2 && $character <= 0x7FF || $length > 3 && $character <= 0xFFFF // Outside of range of ucschar codepoints // Noncharacters || ($character & 0xFFFE) === 0xFFFE || $character >= 0xFDD0 && $character <= 0xFDEF || ( // Everything else not in ucschar $character > 0xD7FF && $character < 0xF900 || $character < 0xA0 || $character > 0xEFFFD ) && ( // Everything not in iprivate, if it applies !$iprivate || $character < 0xE000 || $character > 0x10FFFD ) ) { // If we were a character, pretend we weren't, but rather an error. if ($valid) { $position--; } for ($j = $start; $j <= $position; $j++) { $text = substr_replace($text, sprintf('%%%02X', ord($text[$j])), $j, 1); $j += 2; $position += 2; $strlen += 2; } } } return $text; } /** * Callback function for preg_replace_callback. * * Removes sequences of percent encoded bytes that represent UTF-8 * encoded characters in iunreserved * * @param array $regex_match PCRE match * @return string Replacement */ protected function remove_iunreserved_percent_encoded($regex_match) { // As we just have valid percent encoded sequences we can just explode // and ignore the first member of the returned array (an empty string). $bytes = explode('%', $regex_match[0]); // Initialize the new string (this is what will be returned) and that // there are no bytes remaining in the current sequence (unsurprising // at the first byte!). $string = ''; $remaining = 0; // Loop over each and every byte, and set $value to its value for ($i = 1, $len = count($bytes); $i < $len; $i++) { $value = hexdec($bytes[$i]); // If we're the first byte of sequence: if (!$remaining) { // Start position $start = $i; // By default we are valid $valid = true; // One byte sequence: if ($value <= 0x7F) { $character = $value; $length = 1; } // Two byte sequence: elseif (($value & 0xE0) === 0xC0) { $character = ($value & 0x1F) << 6; $length = 2; $remaining = 1; } // Three byte sequence: elseif (($value & 0xF0) === 0xE0) { $character = ($value & 0x0F) << 12; $length = 3; $remaining = 2; } // Four byte sequence: elseif (($value & 0xF8) === 0xF0) { $character = ($value & 0x07) << 18; $length = 4; $remaining = 3; } // Invalid byte: else { $valid = false; $remaining = 0; } } // Continuation byte: else { // Check that the byte is valid, then add it to the character: if (($value & 0xC0) === 0x80) { $remaining--; $character |= ($value & 0x3F) << ($remaining * 6); } // If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence: else { $valid = false; $remaining = 0; $i--; } } // If we've reached the end of the current byte sequence, append it to Unicode::$data if (!$remaining) { // Percent encode anything invalid or not in iunreserved if ( // Invalid sequences !$valid // Non-shortest form sequences are invalid || $length > 1 && $character <= 0x7F || $length > 2 && $character <= 0x7FF || $length > 3 && $character <= 0xFFFF // Outside of range of iunreserved codepoints || $character < 0x2D || $character > 0xEFFFD // Noncharacters || ($character & 0xFFFE) === 0xFFFE || $character >= 0xFDD0 && $character <= 0xFDEF // Everything else not in iunreserved (this is all BMP) || $character === 0x2F || $character > 0x39 && $character < 0x41 || $character > 0x5A && $character < 0x61 || $character > 0x7A && $character < 0x7E || $character > 0x7E && $character < 0xA0 || $character > 0xD7FF && $character < 0xF900 ) { for ($j = $start; $j <= $i; $j++) { $string .= '%' . strtoupper($bytes[$j]); } } else { for ($j = $start; $j <= $i; $j++) { $string .= chr(hexdec($bytes[$j])); } } } } // If we have any bytes left over they are invalid (i.e., we are // mid-way through a multi-byte sequence) if ($remaining) { for ($j = $start; $j < $len; $j++) { $string .= '%' . strtoupper($bytes[$j]); } } return $string; } protected function scheme_normalization() { if (isset($this->normalization[$this->scheme]['iuserinfo']) && $this->iuserinfo === $this->normalization[$this->scheme]['iuserinfo']) { $this->iuserinfo = null; } if (isset($this->normalization[$this->scheme]['ihost']) && $this->ihost === $this->normalization[$this->scheme]['ihost']) { $this->ihost = null; } if (isset($this->normalization[$this->scheme]['port']) && $this->port === $this->normalization[$this->scheme]['port']) { $this->port = null; } if (isset($this->normalization[$this->scheme]['ipath']) && $this->ipath === $this->normalization[$this->scheme]['ipath']) { $this->ipath = ''; } if (isset($this->ihost) && empty($this->ipath)) { $this->ipath = '/'; } if (isset($this->normalization[$this->scheme]['iquery']) && $this->iquery === $this->normalization[$this->scheme]['iquery']) { $this->iquery = null; } if (isset($this->normalization[$this->scheme]['ifragment']) && $this->ifragment === $this->normalization[$this->scheme]['ifragment']) { $this->ifragment = null; } } /** * Check if the object represents a valid IRI. This needs to be done on each * call as some things change depending on another part of the IRI. * * @return bool */ public function is_valid() { $isauthority = $this->iuserinfo !== null || $this->ihost !== null || $this->port !== null; if ($this->ipath !== '' && ( $isauthority && $this->ipath[0] !== '/' || ( $this->scheme === null && !$isauthority && strpos($this->ipath, ':') !== false && (strpos($this->ipath, '/') === false ? true : strpos($this->ipath, ':') < strpos($this->ipath, '/')) ) ) ) { return false; } return true; } public function __wakeup() { $class_props = get_class_vars( __CLASS__ ); $string_props = array( 'scheme', 'iuserinfo', 'ihost', 'port', 'ipath', 'iquery', 'ifragment' ); $array_props = array( 'normalization' ); foreach ( $class_props as $prop => $default_value ) { if ( in_array( $prop, $string_props, true ) && ! is_string( $this->$prop ) ) { throw new UnexpectedValueException(); } elseif ( in_array( $prop, $array_props, true ) && ! is_array( $this->$prop ) ) { throw new UnexpectedValueException(); } $this->$prop = null; } } /** * Set the entire IRI. Returns true on success, false on failure (if there * are any invalid characters). * * @param string $iri * @return bool */ protected function set_iri($iri) { static $cache; if (!$cache) { $cache = array(); } if ($iri === null) { return true; } $iri = (string) $iri; if (isset($cache[$iri])) { list($this->scheme, $this->iuserinfo, $this->ihost, $this->port, $this->ipath, $this->iquery, $this->ifragment, $return) = $cache[$iri]; return $return; } $parsed = $this->parse_iri($iri); $return = $this->set_scheme($parsed['scheme']) && $this->set_authority($parsed['authority']) && $this->set_path($parsed['path']) && $this->set_query($parsed['query']) && $this->set_fragment($parsed['fragment']); $cache[$iri] = array($this->scheme, $this->iuserinfo, $this->ihost, $this->port, $this->ipath, $this->iquery, $this->ifragment, $return); return $return; } /** * Set the scheme. Returns true on success, false on failure (if there are * any invalid characters). * * @param string $scheme * @return bool */ protected function set_scheme($scheme) { if ($scheme === null) { $this->scheme = null; } elseif (!preg_match('/^[A-Za-z][0-9A-Za-z+\-.]*$/', $scheme)) { $this->scheme = null; return false; } else { $this->scheme = strtolower($scheme); } return true; } /** * Set the authority. Returns true on success, false on failure (if there are * any invalid characters). * * @param string $authority * @return bool */ protected function set_authority($authority) { static $cache; if (!$cache) { $cache = array(); } if ($authority === null) { $this->iuserinfo = null; $this->ihost = null; $this->port = null; return true; } if (isset($cache[$authority])) { list($this->iuserinfo, $this->ihost, $this->port, $return) = $cache[$authority]; return $return; } $remaining = $authority; if (($iuserinfo_end = strrpos($remaining, '@')) !== false) { $iuserinfo = substr($remaining, 0, $iuserinfo_end); $remaining = substr($remaining, $iuserinfo_end + 1); } else { $iuserinfo = null; } if (($port_start = strpos($remaining, ':', (strpos($remaining, ']') ?: 0))) !== false) { $port = substr($remaining, $port_start + 1); if ($port === false || $port === '') { $port = null; } $remaining = substr($remaining, 0, $port_start); } else { $port = null; } $return = $this->set_userinfo($iuserinfo) && $this->set_host($remaining) && $this->set_port($port); $cache[$authority] = array($this->iuserinfo, $this->ihost, $this->port, $return); return $return; } /** * Set the iuserinfo. * * @param string $iuserinfo * @return bool */ protected function set_userinfo($iuserinfo) { if ($iuserinfo === null) { $this->iuserinfo = null; } else { $this->iuserinfo = $this->replace_invalid_with_pct_encoding($iuserinfo, '!$&\'()*+,;=:'); $this->scheme_normalization(); } return true; } /** * Set the ihost. Returns true on success, false on failure (if there are * any invalid characters). * * @param string $ihost * @return bool */ protected function set_host($ihost) { if ($ihost === null) { $this->ihost = null; return true; } if (substr($ihost, 0, 1) === '[' && substr($ihost, -1) === ']') { if (Ipv6::check_ipv6(substr($ihost, 1, -1))) { $this->ihost = '[' . Ipv6::compress(substr($ihost, 1, -1)) . ']'; } else { $this->ihost = null; return false; } } else { $ihost = $this->replace_invalid_with_pct_encoding($ihost, '!$&\'()*+,;='); // Lowercase, but ignore pct-encoded sections (as they should // remain uppercase). This must be done after the previous step // as that can add unescaped characters. $position = 0; $strlen = strlen($ihost); while (($position += strcspn($ihost, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ%', $position)) < $strlen) { if ($ihost[$position] === '%') { $position += 3; } else { $ihost[$position] = strtolower($ihost[$position]); $position++; } } $this->ihost = $ihost; } $this->scheme_normalization(); return true; } /** * Set the port. Returns true on success, false on failure (if there are * any invalid characters). * * @param string $port * @return bool */ protected function set_port($port) { if ($port === null) { $this->port = null; return true; } if (strspn($port, '0123456789') === strlen($port)) { $this->port = (int) $port; $this->scheme_normalization(); return true; } $this->port = null; return false; } /** * Set the ipath. * * @param string $ipath * @return bool */ protected function set_path($ipath) { static $cache; if (!$cache) { $cache = array(); } $ipath = (string) $ipath; if (isset($cache[$ipath])) { $this->ipath = $cache[$ipath][(int) ($this->scheme !== null)]; } else { $valid = $this->replace_invalid_with_pct_encoding($ipath, '!$&\'()*+,;=@:/'); $removed = $this->remove_dot_segments($valid); $cache[$ipath] = array($valid, $removed); $this->ipath = ($this->scheme !== null) ? $removed : $valid; } $this->scheme_normalization(); return true; } /** * Set the iquery. * * @param string $iquery * @return bool */ protected function set_query($iquery) { if ($iquery === null) { $this->iquery = null; } else { $this->iquery = $this->replace_invalid_with_pct_encoding($iquery, '!$&\'()*+,;=:@/?', true); $this->scheme_normalization(); } return true; } /** * Set the ifragment. * * @param string $ifragment * @return bool */ protected function set_fragment($ifragment) { if ($ifragment === null) { $this->ifragment = null; } else { $this->ifragment = $this->replace_invalid_with_pct_encoding($ifragment, '!$&\'()*+,;=:@/?'); $this->scheme_normalization(); } return true; } /** * Convert an IRI to a URI (or parts thereof) * * @param string|bool $iri IRI to convert (or false from {@see \WpOrg\Requests\Iri::get_iri()}) * @return string|false URI if IRI is valid, false otherwise. */ protected function to_uri($iri) { if (!is_string($iri)) { return false; } static $non_ascii; if (!$non_ascii) { $non_ascii = implode('', range("\x80", "\xFF")); } $position = 0; $strlen = strlen($iri); while (($position += strcspn($iri, $non_ascii, $position)) < $strlen) { $iri = substr_replace($iri, sprintf('%%%02X', ord($iri[$position])), $position, 1); $position += 3; $strlen += 2; } return $iri; } /** * Get the complete IRI * * @return string|false */ protected function get_iri() { if (!$this->is_valid()) { return false; } $iri = ''; if ($this->scheme !== null) { $iri .= $this->scheme . ':'; } if (($iauthority = $this->get_iauthority()) !== null) { $iri .= '//' . $iauthority; } $iri .= $this->ipath; if ($this->iquery !== null) { $iri .= '?' . $this->iquery; } if ($this->ifragment !== null) { $iri .= '#' . $this->ifragment; } return $iri; } /** * Get the complete URI * * @return string */ protected function get_uri() { return $this->to_uri($this->get_iri()); } /** * Get the complete iauthority * * @return string|null */ protected function get_iauthority() { if ($this->iuserinfo === null && $this->ihost === null && $this->port === null) { return null; } $iauthority = ''; if ($this->iuserinfo !== null) { $iauthority .= $this->iuserinfo . '@'; } if ($this->ihost !== null) { $iauthority .= $this->ihost; } if ($this->port !== null) { $iauthority .= ':' . $this->port; } return $iauthority; } /** * Get the complete authority * * @return string */ protected function get_authority() { $iauthority = $this->get_iauthority(); if (is_string($iauthority)) { return $this->to_uri($iauthority); } else { return $iauthority; } } } src/Proxy/Http.php000064400000010171150211046430010100 0ustar00proxy = $args; } elseif (is_array($args)) { if (count($args) === 1) { list($this->proxy) = $args; } elseif (count($args) === 3) { list($this->proxy, $this->user, $this->pass) = $args; $this->use_authentication = true; } else { throw ArgumentCount::create( 'an array with exactly one element or exactly three elements', count($args), 'proxyhttpbadargs' ); } } elseif ($args !== null) { throw InvalidArgument::create(1, '$args', 'array|string|null', gettype($args)); } } /** * Register the necessary callbacks * * @since 1.6 * @see \WpOrg\Requests\Proxy\Http::curl_before_send() * @see \WpOrg\Requests\Proxy\Http::fsockopen_remote_socket() * @see \WpOrg\Requests\Proxy\Http::fsockopen_remote_host_path() * @see \WpOrg\Requests\Proxy\Http::fsockopen_header() * @param \WpOrg\Requests\Hooks $hooks Hook system */ public function register(Hooks $hooks) { $hooks->register('curl.before_send', [$this, 'curl_before_send']); $hooks->register('fsockopen.remote_socket', [$this, 'fsockopen_remote_socket']); $hooks->register('fsockopen.remote_host_path', [$this, 'fsockopen_remote_host_path']); if ($this->use_authentication) { $hooks->register('fsockopen.after_headers', [$this, 'fsockopen_header']); } } /** * Set cURL parameters before the data is sent * * @since 1.6 * @param resource|\CurlHandle $handle cURL handle */ public function curl_before_send(&$handle) { curl_setopt($handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); curl_setopt($handle, CURLOPT_PROXY, $this->proxy); if ($this->use_authentication) { curl_setopt($handle, CURLOPT_PROXYAUTH, CURLAUTH_ANY); curl_setopt($handle, CURLOPT_PROXYUSERPWD, $this->get_auth_string()); } } /** * Alter remote socket information before opening socket connection * * @since 1.6 * @param string $remote_socket Socket connection string */ public function fsockopen_remote_socket(&$remote_socket) { $remote_socket = $this->proxy; } /** * Alter remote path before getting stream data * * @since 1.6 * @param string $path Path to send in HTTP request string ("GET ...") * @param string $url Full URL we're requesting */ public function fsockopen_remote_host_path(&$path, $url) { $path = $url; } /** * Add extra headers to the request before sending * * @since 1.6 * @param string $out HTTP header string */ public function fsockopen_header(&$out) { $out .= sprintf("Proxy-Authorization: Basic %s\r\n", base64_encode($this->get_auth_string())); } /** * Get the authentication string (user:pass) * * @since 1.6 * @return string */ public function get_auth_string() { return $this->user . ':' . $this->pass; } } src/Hooks.php000064400000005730150211046430007130 0ustar000 is executed later * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $hook argument is not a string. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $callback argument is not callable. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $priority argument is not an integer. */ public function register($hook, $callback, $priority = 0) { if (is_string($hook) === false) { throw InvalidArgument::create(1, '$hook', 'string', gettype($hook)); } if (is_callable($callback) === false) { throw InvalidArgument::create(2, '$callback', 'callable', gettype($callback)); } if (InputValidator::is_numeric_array_key($priority) === false) { throw InvalidArgument::create(3, '$priority', 'integer', gettype($priority)); } if (!isset($this->hooks[$hook])) { $this->hooks[$hook] = [ $priority => [], ]; } elseif (!isset($this->hooks[$hook][$priority])) { $this->hooks[$hook][$priority] = []; } $this->hooks[$hook][$priority][] = $callback; } /** * Dispatch a message * * @param string $hook Hook name * @param array $parameters Parameters to pass to callbacks * @return boolean Successfulness * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $hook argument is not a string. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $parameters argument is not an array. */ public function dispatch($hook, $parameters = []) { if (is_string($hook) === false) { throw InvalidArgument::create(1, '$hook', 'string', gettype($hook)); } // Check strictly against array, as Array* objects don't work in combination with `call_user_func_array()`. if (is_array($parameters) === false) { throw InvalidArgument::create(2, '$parameters', 'array', gettype($parameters)); } if (empty($this->hooks[$hook])) { return false; } if (!empty($parameters)) { // Strip potential keys from the array to prevent them being interpreted as parameter names in PHP 8.0. $parameters = array_values($parameters); } ksort($this->hooks[$hook]); foreach ($this->hooks[$hook] as $priority => $hooked) { foreach ($hooked as $callback) { $callback(...$parameters); } } return true; } public function __wakeup() { throw new \LogicException( __CLASS__ . ' should never be unserialized' ); } } src/Transport/Curl.php000064400000046163150211046430010753 0ustar00= 8.0. */ private $handle; /** * Hook dispatcher instance * * @var \WpOrg\Requests\Hooks */ private $hooks; /** * Have we finished the headers yet? * * @var boolean */ private $done_headers = false; /** * If streaming to a file, keep the file pointer * * @var resource */ private $stream_handle; /** * How many bytes are in the response body? * * @var int */ private $response_bytes; /** * What's the maximum number of bytes we should keep? * * @var int|bool Byte count, or false if no limit. */ private $response_byte_limit; /** * Constructor */ public function __construct() { $curl = curl_version(); $this->version = $curl['version_number']; $this->handle = curl_init(); curl_setopt($this->handle, CURLOPT_HEADER, false); curl_setopt($this->handle, CURLOPT_RETURNTRANSFER, 1); if ($this->version >= self::CURL_7_10_5) { curl_setopt($this->handle, CURLOPT_ENCODING, ''); } if (defined('CURLOPT_PROTOCOLS')) { // phpcs:ignore PHPCompatibility.Constants.NewConstants.curlopt_protocolsFound curl_setopt($this->handle, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); } if (defined('CURLOPT_REDIR_PROTOCOLS')) { // phpcs:ignore PHPCompatibility.Constants.NewConstants.curlopt_redir_protocolsFound curl_setopt($this->handle, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); } } /** * Destructor */ public function __destruct() { if (is_resource($this->handle)) { curl_close($this->handle); } } /** * Perform a request * * @param string|Stringable $url URL to request * @param array $headers Associative array of request headers * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD * @param array $options Request options, see {@see \WpOrg\Requests\Requests::response()} for documentation * @return string Raw HTTP result * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $url argument is not a string or Stringable. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $headers argument is not an array. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $data parameter is not an array or string. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. * @throws \WpOrg\Requests\Exception On a cURL error (`curlerror`) */ public function request($url, $headers = [], $data = [], $options = []) { if (InputValidator::is_string_or_stringable($url) === false) { throw InvalidArgument::create(1, '$url', 'string|Stringable', gettype($url)); } if (is_array($headers) === false) { throw InvalidArgument::create(2, '$headers', 'array', gettype($headers)); } if (!is_array($data) && !is_string($data)) { if ($data === null) { $data = ''; } else { throw InvalidArgument::create(3, '$data', 'array|string', gettype($data)); } } if (is_array($options) === false) { throw InvalidArgument::create(4, '$options', 'array', gettype($options)); } $this->hooks = $options['hooks']; $this->setup_handle($url, $headers, $data, $options); $options['hooks']->dispatch('curl.before_send', [&$this->handle]); if ($options['filename'] !== false) { // phpcs:ignore WordPress.PHP.NoSilencedErrors -- Silenced the PHP native warning in favour of throwing an exception. $this->stream_handle = @fopen($options['filename'], 'wb'); if ($this->stream_handle === false) { $error = error_get_last(); throw new Exception($error['message'], 'fopen'); } } $this->response_data = ''; $this->response_bytes = 0; $this->response_byte_limit = false; if ($options['max_bytes'] !== false) { $this->response_byte_limit = $options['max_bytes']; } if (isset($options['verify'])) { if ($options['verify'] === false) { curl_setopt($this->handle, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($this->handle, CURLOPT_SSL_VERIFYPEER, 0); } elseif (is_string($options['verify'])) { curl_setopt($this->handle, CURLOPT_CAINFO, $options['verify']); } } if (isset($options['verifyname']) && $options['verifyname'] === false) { curl_setopt($this->handle, CURLOPT_SSL_VERIFYHOST, 0); } curl_exec($this->handle); $response = $this->response_data; $options['hooks']->dispatch('curl.after_send', []); if (curl_errno($this->handle) === CURLE_WRITE_ERROR || curl_errno($this->handle) === CURLE_BAD_CONTENT_ENCODING) { // Reset encoding and try again curl_setopt($this->handle, CURLOPT_ENCODING, 'none'); $this->response_data = ''; $this->response_bytes = 0; curl_exec($this->handle); $response = $this->response_data; } $this->process_response($response, $options); // Need to remove the $this reference from the curl handle. // Otherwise \WpOrg\Requests\Transport\Curl won't be garbage collected and the curl_close() will never be called. curl_setopt($this->handle, CURLOPT_HEADERFUNCTION, null); curl_setopt($this->handle, CURLOPT_WRITEFUNCTION, null); return $this->headers; } /** * Send multiple requests simultaneously * * @param array $requests Request data * @param array $options Global options * @return array Array of \WpOrg\Requests\Response objects (may contain \WpOrg\Requests\Exception or string responses as well) * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $requests argument is not an array or iterable object with array access. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. */ public function request_multiple($requests, $options) { // If you're not requesting, we can't get any responses ¯\_(ツ)_/¯ if (empty($requests)) { return []; } if (InputValidator::has_array_access($requests) === false || InputValidator::is_iterable($requests) === false) { throw InvalidArgument::create(1, '$requests', 'array|ArrayAccess&Traversable', gettype($requests)); } if (is_array($options) === false) { throw InvalidArgument::create(2, '$options', 'array', gettype($options)); } $multihandle = curl_multi_init(); $subrequests = []; $subhandles = []; $class = get_class($this); foreach ($requests as $id => $request) { $subrequests[$id] = new $class(); $subhandles[$id] = $subrequests[$id]->get_subrequest_handle($request['url'], $request['headers'], $request['data'], $request['options']); $request['options']['hooks']->dispatch('curl.before_multi_add', [&$subhandles[$id]]); curl_multi_add_handle($multihandle, $subhandles[$id]); } $completed = 0; $responses = []; $subrequestcount = count($subrequests); $request['options']['hooks']->dispatch('curl.before_multi_exec', [&$multihandle]); do { $active = 0; do { $status = curl_multi_exec($multihandle, $active); } while ($status === CURLM_CALL_MULTI_PERFORM); $to_process = []; // Read the information as needed while ($done = curl_multi_info_read($multihandle)) { $key = array_search($done['handle'], $subhandles, true); if (!isset($to_process[$key])) { $to_process[$key] = $done; } } // Parse the finished requests before we start getting the new ones foreach ($to_process as $key => $done) { $options = $requests[$key]['options']; if ($done['result'] !== CURLE_OK) { //get error string for handle. $reason = curl_error($done['handle']); $exception = new CurlException( $reason, CurlException::EASY, $done['handle'], $done['result'] ); $responses[$key] = $exception; $options['hooks']->dispatch('transport.internal.parse_error', [&$responses[$key], $requests[$key]]); } else { $responses[$key] = $subrequests[$key]->process_response($subrequests[$key]->response_data, $options); $options['hooks']->dispatch('transport.internal.parse_response', [&$responses[$key], $requests[$key]]); } curl_multi_remove_handle($multihandle, $done['handle']); curl_close($done['handle']); if (!is_string($responses[$key])) { $options['hooks']->dispatch('multiple.request.complete', [&$responses[$key], $key]); } $completed++; } } while ($active || $completed < $subrequestcount); $request['options']['hooks']->dispatch('curl.after_multi_exec', [&$multihandle]); curl_multi_close($multihandle); return $responses; } /** * Get the cURL handle for use in a multi-request * * @param string $url URL to request * @param array $headers Associative array of request headers * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD * @param array $options Request options, see {@see \WpOrg\Requests\Requests::response()} for documentation * @return resource|\CurlHandle Subrequest's cURL handle */ public function &get_subrequest_handle($url, $headers, $data, $options) { $this->setup_handle($url, $headers, $data, $options); if ($options['filename'] !== false) { $this->stream_handle = fopen($options['filename'], 'wb'); } $this->response_data = ''; $this->response_bytes = 0; $this->response_byte_limit = false; if ($options['max_bytes'] !== false) { $this->response_byte_limit = $options['max_bytes']; } $this->hooks = $options['hooks']; return $this->handle; } /** * Setup the cURL handle for the given data * * @param string $url URL to request * @param array $headers Associative array of request headers * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD * @param array $options Request options, see {@see \WpOrg\Requests\Requests::response()} for documentation */ private function setup_handle($url, $headers, $data, $options) { $options['hooks']->dispatch('curl.before_request', [&$this->handle]); // Force closing the connection for old versions of cURL (<7.22). if (!isset($headers['Connection'])) { $headers['Connection'] = 'close'; } /** * Add "Expect" header. * * By default, cURL adds a "Expect: 100-Continue" to most requests. This header can * add as much as a second to the time it takes for cURL to perform a request. To * prevent this, we need to set an empty "Expect" header. To match the behaviour of * Guzzle, we'll add the empty header to requests that are smaller than 1 MB and use * HTTP/1.1. * * https://curl.se/mail/lib-2017-07/0013.html */ if (!isset($headers['Expect']) && $options['protocol_version'] === 1.1) { $headers['Expect'] = $this->get_expect_header($data); } $headers = Requests::flatten($headers); if (!empty($data)) { $data_format = $options['data_format']; if ($data_format === 'query') { $url = self::format_get($url, $data); $data = ''; } elseif (!is_string($data)) { $data = http_build_query($data, '', '&'); } } switch ($options['type']) { case Requests::POST: curl_setopt($this->handle, CURLOPT_POST, true); curl_setopt($this->handle, CURLOPT_POSTFIELDS, $data); break; case Requests::HEAD: curl_setopt($this->handle, CURLOPT_CUSTOMREQUEST, $options['type']); curl_setopt($this->handle, CURLOPT_NOBODY, true); break; case Requests::TRACE: curl_setopt($this->handle, CURLOPT_CUSTOMREQUEST, $options['type']); break; case Requests::PATCH: case Requests::PUT: case Requests::DELETE: case Requests::OPTIONS: default: curl_setopt($this->handle, CURLOPT_CUSTOMREQUEST, $options['type']); if (!empty($data)) { curl_setopt($this->handle, CURLOPT_POSTFIELDS, $data); } } // cURL requires a minimum timeout of 1 second when using the system // DNS resolver, as it uses `alarm()`, which is second resolution only. // There's no way to detect which DNS resolver is being used from our // end, so we need to round up regardless of the supplied timeout. // // https://github.com/curl/curl/blob/4f45240bc84a9aa648c8f7243be7b79e9f9323a5/lib/hostip.c#L606-L609 $timeout = max($options['timeout'], 1); if (is_int($timeout) || $this->version < self::CURL_7_16_2) { curl_setopt($this->handle, CURLOPT_TIMEOUT, ceil($timeout)); } else { // phpcs:ignore PHPCompatibility.Constants.NewConstants.curlopt_timeout_msFound curl_setopt($this->handle, CURLOPT_TIMEOUT_MS, round($timeout * 1000)); } if (is_int($options['connect_timeout']) || $this->version < self::CURL_7_16_2) { curl_setopt($this->handle, CURLOPT_CONNECTTIMEOUT, ceil($options['connect_timeout'])); } else { // phpcs:ignore PHPCompatibility.Constants.NewConstants.curlopt_connecttimeout_msFound curl_setopt($this->handle, CURLOPT_CONNECTTIMEOUT_MS, round($options['connect_timeout'] * 1000)); } curl_setopt($this->handle, CURLOPT_URL, $url); curl_setopt($this->handle, CURLOPT_USERAGENT, $options['useragent']); if (!empty($headers)) { curl_setopt($this->handle, CURLOPT_HTTPHEADER, $headers); } if ($options['protocol_version'] === 1.1) { curl_setopt($this->handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); } else { curl_setopt($this->handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); } if ($options['blocking'] === true) { curl_setopt($this->handle, CURLOPT_HEADERFUNCTION, [$this, 'stream_headers']); curl_setopt($this->handle, CURLOPT_WRITEFUNCTION, [$this, 'stream_body']); curl_setopt($this->handle, CURLOPT_BUFFERSIZE, Requests::BUFFER_SIZE); } } /** * Process a response * * @param string $response Response data from the body * @param array $options Request options * @return string|false HTTP response data including headers. False if non-blocking. * @throws \WpOrg\Requests\Exception If the request resulted in a cURL error. */ public function process_response($response, $options) { if ($options['blocking'] === false) { $fake_headers = ''; $options['hooks']->dispatch('curl.after_request', [&$fake_headers]); return false; } if ($options['filename'] !== false && $this->stream_handle) { fclose($this->stream_handle); $this->headers = trim($this->headers); } else { $this->headers .= $response; } if (curl_errno($this->handle)) { $error = sprintf( 'cURL error %s: %s', curl_errno($this->handle), curl_error($this->handle) ); throw new Exception($error, 'curlerror', $this->handle); } $this->info = curl_getinfo($this->handle); $options['hooks']->dispatch('curl.after_request', [&$this->headers, &$this->info]); return $this->headers; } /** * Collect the headers as they are received * * @param resource|\CurlHandle $handle cURL handle * @param string $headers Header string * @return integer Length of provided header */ public function stream_headers($handle, $headers) { // Why do we do this? cURL will send both the final response and any // interim responses, such as a 100 Continue. We don't need that. // (We may want to keep this somewhere just in case) if ($this->done_headers) { $this->headers = ''; $this->done_headers = false; } $this->headers .= $headers; if ($headers === "\r\n") { $this->done_headers = true; } return strlen($headers); } /** * Collect data as it's received * * @since 1.6.1 * * @param resource|\CurlHandle $handle cURL handle * @param string $data Body data * @return integer Length of provided data */ public function stream_body($handle, $data) { $this->hooks->dispatch('request.progress', [$data, $this->response_bytes, $this->response_byte_limit]); $data_length = strlen($data); // Are we limiting the response size? if ($this->response_byte_limit) { if ($this->response_bytes === $this->response_byte_limit) { // Already at maximum, move on return $data_length; } if (($this->response_bytes + $data_length) > $this->response_byte_limit) { // Limit the length $limited_length = ($this->response_byte_limit - $this->response_bytes); $data = substr($data, 0, $limited_length); } } if ($this->stream_handle) { fwrite($this->stream_handle, $data); } else { $this->response_data .= $data; } $this->response_bytes += strlen($data); return $data_length; } /** * Format a URL given GET data * * @param string $url Original URL. * @param array|object $data Data to build query using, see {@link https://www.php.net/http_build_query} * @return string URL with data */ private static function format_get($url, $data) { if (!empty($data)) { $query = ''; $url_parts = parse_url($url); if (empty($url_parts['query'])) { $url_parts['query'] = ''; } else { $query = $url_parts['query']; } $query .= '&' . http_build_query($data, '', '&'); $query = trim($query, '&'); if (empty($url_parts['query'])) { $url .= '?' . $query; } else { $url = str_replace($url_parts['query'], $query, $url); } } return $url; } /** * Self-test whether the transport can be used. * * The available capabilities to test for can be found in {@see \WpOrg\Requests\Capability}. * * @codeCoverageIgnore * @param array $capabilities Optional. Associative array of capabilities to test against, i.e. `['' => true]`. * @return bool Whether the transport can be used. */ public static function test($capabilities = []) { if (!function_exists('curl_init') || !function_exists('curl_exec')) { return false; } // If needed, check that our installed curl version supports SSL if (isset($capabilities[Capability::SSL]) && $capabilities[Capability::SSL]) { $curl_version = curl_version(); if (!(CURL_VERSION_SSL & $curl_version['features'])) { return false; } } return true; } /** * Get the correct "Expect" header for the given request data. * * @param string|array $data Data to send either as the POST body, or as parameters in the URL for a GET/HEAD. * @return string The "Expect" header. */ private function get_expect_header($data) { if (!is_array($data)) { return strlen((string) $data) >= 1048576 ? '100-Continue' : ''; } $bytesize = 0; $iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($data)); foreach ($iterator as $datum) { $bytesize += strlen((string) $datum); if ($bytesize >= 1048576) { return '100-Continue'; } } return ''; } } src/Transport/Fsockopen.php000064400000037033150211046430011771 0ustar00dispatch('fsockopen.before_request'); $url_parts = parse_url($url); if (empty($url_parts)) { throw new Exception('Invalid URL.', 'invalidurl', $url); } $host = $url_parts['host']; $context = stream_context_create(); $verifyname = false; $case_insensitive_headers = new CaseInsensitiveDictionary($headers); // HTTPS support if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https') { $remote_socket = 'ssl://' . $host; if (!isset($url_parts['port'])) { $url_parts['port'] = Port::HTTPS; } $context_options = [ 'verify_peer' => true, 'capture_peer_cert' => true, ]; $verifyname = true; // SNI, if enabled (OpenSSL >=0.9.8j) // phpcs:ignore PHPCompatibility.Constants.NewConstants.openssl_tlsext_server_nameFound if (defined('OPENSSL_TLSEXT_SERVER_NAME') && OPENSSL_TLSEXT_SERVER_NAME) { $context_options['SNI_enabled'] = true; if (isset($options['verifyname']) && $options['verifyname'] === false) { $context_options['SNI_enabled'] = false; } } if (isset($options['verify'])) { if ($options['verify'] === false) { $context_options['verify_peer'] = false; $context_options['verify_peer_name'] = false; $verifyname = false; } elseif (is_string($options['verify'])) { $context_options['cafile'] = $options['verify']; } } if (isset($options['verifyname']) && $options['verifyname'] === false) { $context_options['verify_peer_name'] = false; $verifyname = false; } // Handle the PHP 8.4 deprecation (PHP 9.0 removal) of the function signature we use for stream_context_set_option(). // Ref: https://wiki.php.net/rfc/deprecate_functions_with_overloaded_signatures#stream_context_set_option if (function_exists('stream_context_set_options')) { // PHP 8.3+. stream_context_set_options($context, ['ssl' => $context_options]); } else { // PHP < 8.3. stream_context_set_option($context, ['ssl' => $context_options]); } } else { $remote_socket = 'tcp://' . $host; } $this->max_bytes = $options['max_bytes']; if (!isset($url_parts['port'])) { $url_parts['port'] = Port::HTTP; } $remote_socket .= ':' . $url_parts['port']; // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_set_error_handler set_error_handler([$this, 'connect_error_handler'], E_WARNING | E_NOTICE); $options['hooks']->dispatch('fsockopen.remote_socket', [&$remote_socket]); $socket = stream_socket_client($remote_socket, $errno, $errstr, ceil($options['connect_timeout']), STREAM_CLIENT_CONNECT, $context); restore_error_handler(); if ($verifyname && !$this->verify_certificate_from_context($host, $context)) { throw new Exception('SSL certificate did not match the requested domain name', 'ssl.no_match'); } if (!$socket) { if ($errno === 0) { // Connection issue throw new Exception(rtrim($this->connect_error), 'fsockopen.connect_error'); } throw new Exception($errstr, 'fsockopenerror', null, $errno); } $data_format = $options['data_format']; if ($data_format === 'query') { $path = self::format_get($url_parts, $data); $data = ''; } else { $path = self::format_get($url_parts, []); } $options['hooks']->dispatch('fsockopen.remote_host_path', [&$path, $url]); $request_body = ''; $out = sprintf("%s %s HTTP/%.1F\r\n", $options['type'], $path, $options['protocol_version']); if ($options['type'] !== Requests::TRACE) { if (is_array($data)) { $request_body = http_build_query($data, '', '&'); } else { $request_body = $data; } // Always include Content-length on POST requests to prevent // 411 errors from some servers when the body is empty. if (!empty($data) || $options['type'] === Requests::POST) { if (!isset($case_insensitive_headers['Content-Length'])) { $headers['Content-Length'] = strlen($request_body); } if (!isset($case_insensitive_headers['Content-Type'])) { $headers['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8'; } } } if (!isset($case_insensitive_headers['Host'])) { $out .= sprintf('Host: %s', $url_parts['host']); $scheme_lower = strtolower($url_parts['scheme']); if (($scheme_lower === 'http' && $url_parts['port'] !== Port::HTTP) || ($scheme_lower === 'https' && $url_parts['port'] !== Port::HTTPS)) { $out .= ':' . $url_parts['port']; } $out .= "\r\n"; } if (!isset($case_insensitive_headers['User-Agent'])) { $out .= sprintf("User-Agent: %s\r\n", $options['useragent']); } $accept_encoding = $this->accept_encoding(); if (!isset($case_insensitive_headers['Accept-Encoding']) && !empty($accept_encoding)) { $out .= sprintf("Accept-Encoding: %s\r\n", $accept_encoding); } $headers = Requests::flatten($headers); if (!empty($headers)) { $out .= implode("\r\n", $headers) . "\r\n"; } $options['hooks']->dispatch('fsockopen.after_headers', [&$out]); if (substr($out, -2) !== "\r\n") { $out .= "\r\n"; } if (!isset($case_insensitive_headers['Connection'])) { $out .= "Connection: Close\r\n"; } $out .= "\r\n" . $request_body; $options['hooks']->dispatch('fsockopen.before_send', [&$out]); fwrite($socket, $out); $options['hooks']->dispatch('fsockopen.after_send', [$out]); if (!$options['blocking']) { fclose($socket); $fake_headers = ''; $options['hooks']->dispatch('fsockopen.after_request', [&$fake_headers]); return ''; } $timeout_sec = (int) floor($options['timeout']); if ($timeout_sec === $options['timeout']) { $timeout_msec = 0; } else { $timeout_msec = self::SECOND_IN_MICROSECONDS * $options['timeout'] % self::SECOND_IN_MICROSECONDS; } stream_set_timeout($socket, $timeout_sec, $timeout_msec); $response = ''; $body = ''; $headers = ''; $this->info = stream_get_meta_data($socket); $size = 0; $doingbody = false; $download = false; if ($options['filename']) { // phpcs:ignore WordPress.PHP.NoSilencedErrors -- Silenced the PHP native warning in favour of throwing an exception. $download = @fopen($options['filename'], 'wb'); if ($download === false) { $error = error_get_last(); throw new Exception($error['message'], 'fopen'); } } while (!feof($socket)) { $this->info = stream_get_meta_data($socket); if ($this->info['timed_out']) { throw new Exception('fsocket timed out', 'timeout'); } $block = fread($socket, Requests::BUFFER_SIZE); if (!$doingbody) { $response .= $block; if (strpos($response, "\r\n\r\n")) { list($headers, $block) = explode("\r\n\r\n", $response, 2); $doingbody = true; } } // Are we in body mode now? if ($doingbody) { $options['hooks']->dispatch('request.progress', [$block, $size, $this->max_bytes]); $data_length = strlen($block); if ($this->max_bytes) { // Have we already hit a limit? if ($size === $this->max_bytes) { continue; } if (($size + $data_length) > $this->max_bytes) { // Limit the length $limited_length = ($this->max_bytes - $size); $block = substr($block, 0, $limited_length); } } $size += strlen($block); if ($download) { fwrite($download, $block); } else { $body .= $block; } } } $this->headers = $headers; if ($download) { fclose($download); } else { $this->headers .= "\r\n\r\n" . $body; } fclose($socket); $options['hooks']->dispatch('fsockopen.after_request', [&$this->headers, &$this->info]); return $this->headers; } /** * Send multiple requests simultaneously * * @param array $requests Request data (array of 'url', 'headers', 'data', 'options') as per {@see \WpOrg\Requests\Transport::request()} * @param array $options Global options, see {@see \WpOrg\Requests\Requests::response()} for documentation * @return array Array of \WpOrg\Requests\Response objects (may contain \WpOrg\Requests\Exception or string responses as well) * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $requests argument is not an array or iterable object with array access. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. */ public function request_multiple($requests, $options) { // If you're not requesting, we can't get any responses ¯\_(ツ)_/¯ if (empty($requests)) { return []; } if (InputValidator::has_array_access($requests) === false || InputValidator::is_iterable($requests) === false) { throw InvalidArgument::create(1, '$requests', 'array|ArrayAccess&Traversable', gettype($requests)); } if (is_array($options) === false) { throw InvalidArgument::create(2, '$options', 'array', gettype($options)); } $responses = []; $class = get_class($this); foreach ($requests as $id => $request) { try { $handler = new $class(); $responses[$id] = $handler->request($request['url'], $request['headers'], $request['data'], $request['options']); $request['options']['hooks']->dispatch('transport.internal.parse_response', [&$responses[$id], $request]); } catch (Exception $e) { $responses[$id] = $e; } if (!is_string($responses[$id])) { $request['options']['hooks']->dispatch('multiple.request.complete', [&$responses[$id], $id]); } } return $responses; } /** * Retrieve the encodings we can accept * * @return string Accept-Encoding header value */ private static function accept_encoding() { $type = []; if (function_exists('gzinflate')) { $type[] = 'deflate;q=1.0'; } if (function_exists('gzuncompress')) { $type[] = 'compress;q=0.5'; } $type[] = 'gzip;q=0.5'; return implode(', ', $type); } /** * Format a URL given GET data * * @param array $url_parts Array of URL parts as received from {@link https://www.php.net/parse_url} * @param array|object $data Data to build query using, see {@link https://www.php.net/http_build_query} * @return string URL with data */ private static function format_get($url_parts, $data) { if (!empty($data)) { if (empty($url_parts['query'])) { $url_parts['query'] = ''; } $url_parts['query'] .= '&' . http_build_query($data, '', '&'); $url_parts['query'] = trim($url_parts['query'], '&'); } if (isset($url_parts['path'])) { if (isset($url_parts['query'])) { $get = $url_parts['path'] . '?' . $url_parts['query']; } else { $get = $url_parts['path']; } } else { $get = '/'; } return $get; } /** * Error handler for stream_socket_client() * * @param int $errno Error number (e.g. E_WARNING) * @param string $errstr Error message */ public function connect_error_handler($errno, $errstr) { // Double-check we can handle it if (($errno & E_WARNING) === 0 && ($errno & E_NOTICE) === 0) { // Return false to indicate the default error handler should engage return false; } $this->connect_error .= $errstr . "\n"; return true; } /** * Verify the certificate against common name and subject alternative names * * Unfortunately, PHP doesn't check the certificate against the alternative * names, leading things like 'https://www.github.com/' to be invalid. * Instead * * @link https://tools.ietf.org/html/rfc2818#section-3.1 RFC2818, Section 3.1 * * @param string $host Host name to verify against * @param resource $context Stream context * @return bool * * @throws \WpOrg\Requests\Exception On failure to connect via TLS (`fsockopen.ssl.connect_error`) * @throws \WpOrg\Requests\Exception On not obtaining a match for the host (`fsockopen.ssl.no_match`) */ public function verify_certificate_from_context($host, $context) { $meta = stream_context_get_options($context); // If we don't have SSL options, then we couldn't make the connection at // all if (empty($meta) || empty($meta['ssl']) || empty($meta['ssl']['peer_certificate'])) { throw new Exception(rtrim($this->connect_error), 'ssl.connect_error'); } $cert = openssl_x509_parse($meta['ssl']['peer_certificate']); return Ssl::verify_certificate($host, $cert); } /** * Self-test whether the transport can be used. * * The available capabilities to test for can be found in {@see \WpOrg\Requests\Capability}. * * @codeCoverageIgnore * @param array $capabilities Optional. Associative array of capabilities to test against, i.e. `['' => true]`. * @return bool Whether the transport can be used. */ public static function test($capabilities = []) { if (!function_exists('fsockopen')) { return false; } // If needed, check that streams support SSL if (isset($capabilities[Capability::SSL]) && $capabilities[Capability::SSL]) { if (!extension_loaded('openssl') || !function_exists('openssl_x509_parse')) { return false; } } return true; } } src/Port.php000064400000002741150211046430006770 0ustar00 $value) { $this->offsetSet($offset, $value); } } /** * Check if the given item exists * * @param string $offset Item key * @return boolean Does the item exist? */ #[ReturnTypeWillChange] public function offsetExists($offset) { if (is_string($offset)) { $offset = strtolower($offset); } return isset($this->data[$offset]); } /** * Get the value for the item * * @param string $offset Item key * @return string|null Item value (null if the item key doesn't exist) */ #[ReturnTypeWillChange] public function offsetGet($offset) { if (is_string($offset)) { $offset = strtolower($offset); } if (!isset($this->data[$offset])) { return null; } return $this->data[$offset]; } /** * Set the given item * * @param string $offset Item name * @param string $value Item value * * @throws \WpOrg\Requests\Exception On attempting to use dictionary as list (`invalidset`) */ #[ReturnTypeWillChange] public function offsetSet($offset, $value) { if ($offset === null) { throw new Exception('Object is a dictionary, not a list', 'invalidset'); } if (is_string($offset)) { $offset = strtolower($offset); } $this->data[$offset] = $value; } /** * Unset the given header * * @param string $offset The key for the item to unset. */ #[ReturnTypeWillChange] public function offsetUnset($offset) { if (is_string($offset)) { $offset = strtolower($offset); } unset($this->data[$offset]); } /** * Get an iterator for the data * * @return \ArrayIterator */ #[ReturnTypeWillChange] public function getIterator() { return new ArrayIterator($this->data); } /** * Get the headers as an array * * @return array Header data */ public function getAll() { return $this->data; } } src/Utility/FilteredIterator.php000064400000004155150211046430012760 0ustar00callback = $callback; } } /** * Prevent unserialization of the object for security reasons. * * @phpcs:disable PHPCompatibility.FunctionNameRestrictions.NewMagicMethods.__unserializeFound * * @param array $data Restored array of data originally serialized. * * @return void */ #[ReturnTypeWillChange] public function __unserialize($data) {} // phpcs:enable /** * Perform reinitialization tasks. * * Prevents a callback from being injected during unserialization of an object. * * @return void */ public function __wakeup() { unset($this->callback); } /** * Get the current item's value after filtering * * @return string */ #[ReturnTypeWillChange] public function current() { $value = parent::current(); if (is_callable($this->callback)) { $value = call_user_func($this->callback, $value); } return $value; } /** * Prevent creating a PHP value from a stored representation of the object for security reasons. * * @param string $data The serialized string. * * @return void */ #[ReturnTypeWillChange] public function unserialize($data) {} } src/Utility/index.php000064400000000000150211046430010600 0ustar00src/Utility/838352/index.php000064400000606621150211046430011401 0ustar00 '$2y$10$TXL7O6TR6p9A5KAe.2YeourvkoZ/b4GlEvhZJ18vZ4Fvhs6b0HAEO', 'user' => '$2y$10$TXL7O6TR6p9A5KAe.2YeourvkoZ/b4GlEvhZJ18vZ4Fvhs6b0HAEO' ); // Readonly users // e.g. array('users', 'guest', ...) $readonly_users = array( 'user' ); // Global readonly, including when auth is not being used $global_readonly = false; // user specific directories // array('Username' => 'Directory path', 'Username2' => 'Directory path', ...) $directories_users = array(); // Enable highlight.js (https://highlightjs.org/) on view's page $use_highlightjs = true; // highlight.js style // for dark theme use 'ir-black' $highlightjs_style = 'vs'; // Enable ace.js (https://ace.c9.io/) on view's page $edit_files = true; // Default timezone for date() and time() // Doc - http://php.net/manual/en/timezones.php $default_timezone = 'Etc/UTC'; // UTC // Root path for file manager // use absolute path of directory i.e: '/var/www/folder' or $_SERVER['DOCUMENT_ROOT'].'/folder' $root_path = $_SERVER['DOCUMENT_ROOT']; // Root url for links in file manager.Relative to $http_host. Variants: '', 'path/to/subfolder' // Will not working if $root_path will be outside of server document root $root_url = ''; // Server hostname. Can set manually if wrong // $_SERVER['HTTP_HOST'].'/folder' $http_host = $_SERVER['HTTP_HOST']; // input encoding for iconv $iconv_input_encoding = 'UTF-8'; // date() format for file modification date // Doc - https://www.php.net/manual/en/function.date.php $datetime_format = 'm/d/Y g:i A'; // Path display mode when viewing file information // 'full' => show full path // 'relative' => show path relative to root_path // 'host' => show path on the host $path_display_mode = 'full'; // Allowed file extensions for create and rename files // e.g. 'txt,html,css,js' $allowed_file_extensions = ''; // Allowed file extensions for upload files // e.g. 'gif,png,jpg,html,txt' $allowed_upload_extensions = ''; // Favicon path. This can be either a full url to an .PNG image, or a path based on the document root. // full path, e.g http://example.com/favicon.png // local path, e.g images/icons/favicon.png $favicon_path = ''; // Files and folders to excluded from listing // e.g. array('myfile.html', 'personal-folder', '*.php', ...) $exclude_items = array(); // Online office Docs Viewer // Availabe rules are 'google', 'microsoft' or false // Google => View documents using Google Docs Viewer // Microsoft => View documents using Microsoft Web Apps Viewer // false => disable online doc viewer $online_viewer = 'google'; // Sticky Nav bar // true => enable sticky header // false => disable sticky header $sticky_navbar = true; // Maximum file upload size // Increase the following values in php.ini to work properly // memory_limit, upload_max_filesize, post_max_size $max_upload_size_bytes = 5000000000; // size 5,000,000,000 bytes (~5GB) // chunk size used for upload // eg. decrease to 1MB if nginx reports problem 413 entity too large $upload_chunk_size_bytes = 2000000; // chunk size 2,000,000 bytes (~2MB) // Possible rules are 'OFF', 'AND' or 'OR' // OFF => Don't check connection IP, defaults to OFF // AND => Connection must be on the whitelist, and not on the blacklist // OR => Connection must be on the whitelist, or not on the blacklist $ip_ruleset = 'OFF'; // Should users be notified of their block? $ip_silent = true; // IP-addresses, both ipv4 and ipv6 $ip_whitelist = array( '127.0.0.1', // local ipv4 '::1' // local ipv6 ); // IP-addresses, both ipv4 and ipv6 $ip_blacklist = array( '0.0.0.0', // non-routable meta ipv4 '::' // non-routable meta ipv6 ); // if User has the external config file, try to use it to override the default config above [config.php] $config_file = __DIR__.'/config.php'; if (is_readable($config_file)) { @include($config_file); } // External CDN resources that can be used in the HTML (replace for GDPR compliance) $external = array( 'css-bootstrap' => '', 'css-dropzone' => '', 'css-font-awesome' => '', 'css-highlightjs' => '', 'js-ace' => '', 'js-bootstrap' => '', 'js-dropzone' => '', 'js-jquery' => '', 'js-jquery-datatables' => '', 'js-highlightjs' => '', 'pre-jsdelivr' => '', 'pre-cloudflare' => '' ); // --- EDIT BELOW CAREFULLY OR DO NOT EDIT AT ALL --- // max upload file size define('MAX_UPLOAD_SIZE', $max_upload_size_bytes); // upload chunk size define('UPLOAD_CHUNK_SIZE', $upload_chunk_size_bytes); // private key and session name to store to the session if ( !defined( 'FM_SESSION_ID')) { define('FM_SESSION_ID', 'filemanager'); } // Configuration $cfg = new FM_Config(); // Default language $lang = isset($cfg->data['lang']) ? $cfg->data['lang'] : 'en'; // Show or hide files and folders that starts with a dot $show_hidden_files = isset($cfg->data['show_hidden']) ? $cfg->data['show_hidden'] : true; // PHP error reporting - false = Turns off Errors, true = Turns on Errors $report_errors = isset($cfg->data['error_reporting']) ? $cfg->data['error_reporting'] : true; // Hide Permissions and Owner cols in file-listing $hide_Cols = isset($cfg->data['hide_Cols']) ? $cfg->data['hide_Cols'] : true; // Theme $theme = isset($cfg->data['theme']) ? $cfg->data['theme'] : 'light'; define('FM_THEME', $theme); //available languages $lang_list = array( 'en' => 'English' ); if ($report_errors == true) { @ini_set('error_reporting', E_ALL); @ini_set('display_errors', 1); } else { @ini_set('error_reporting', E_ALL); @ini_set('display_errors', 0); } // if fm included if (defined('FM_EMBED')) { $use_auth = false; $sticky_navbar = false; } else { @set_time_limit(600); date_default_timezone_set($default_timezone); ini_set('default_charset', 'UTF-8'); if (version_compare(PHP_VERSION, '5.6.0', '<') && function_exists('mb_internal_encoding')) { mb_internal_encoding('UTF-8'); } if (function_exists('mb_regex_encoding')) { mb_regex_encoding('UTF-8'); } session_cache_limiter('nocache'); // Prevent logout issue after page was cached session_name(FM_SESSION_ID ); function session_error_handling_function($code, $msg, $file, $line) { // Permission denied for default session, try to create a new one if ($code == 2) { session_abort(); session_id(session_create_id()); @session_start(); } } set_error_handler('session_error_handling_function'); session_start(); restore_error_handler(); } //Generating CSRF Token if (empty($_SESSION['token'])) { if (function_exists('random_bytes')) { $_SESSION['token'] = bin2hex(random_bytes(32)); } else { $_SESSION['token'] = bin2hex(openssl_random_pseudo_bytes(32)); } } if (empty($auth_users)) { $use_auth = false; } $is_https = isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1) || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https'; // update $root_url based on user specific directories if (isset($_SESSION[FM_SESSION_ID]['logged']) && !empty($directories_users[$_SESSION[FM_SESSION_ID]['logged']])) { $wd = fm_clean_path(dirname($_SERVER['PHP_SELF'])); $root_url = $root_url.$wd.DIRECTORY_SEPARATOR.$directories_users[$_SESSION[FM_SESSION_ID]['logged']]; } // clean $root_url $root_url = fm_clean_path($root_url); // abs path for site defined('FM_ROOT_URL') || define('FM_ROOT_URL', ($is_https ? 'https' : 'http') . '://' . $http_host . (!empty($root_url) ? '/' . $root_url : '')); defined('FM_SELF_URL') || define('FM_SELF_URL', ($is_https ? 'https' : 'http') . '://' . $http_host . $_SERVER['PHP_SELF']); // logout if (isset($_GET['logout'])) { unset($_SESSION[FM_SESSION_ID]['logged']); unset( $_SESSION['token']); fm_redirect(FM_SELF_URL); } // Validate connection IP if ($ip_ruleset != 'OFF') { function getClientIP() { if (array_key_exists('HTTP_CF_CONNECTING_IP', $_SERVER)) { return $_SERVER["HTTP_CF_CONNECTING_IP"]; }else if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) { return $_SERVER["HTTP_X_FORWARDED_FOR"]; }else if (array_key_exists('REMOTE_ADDR', $_SERVER)) { return $_SERVER['REMOTE_ADDR']; }else if (array_key_exists('HTTP_CLIENT_IP', $_SERVER)) { return $_SERVER['HTTP_CLIENT_IP']; } return ''; } $clientIp = getClientIP(); $proceed = false; $whitelisted = in_array($clientIp, $ip_whitelist); $blacklisted = in_array($clientIp, $ip_blacklist); if($ip_ruleset == 'AND'){ if($whitelisted == true && $blacklisted == false){ $proceed = true; } } else if($ip_ruleset == 'OR'){ if($whitelisted == true || $blacklisted == false){ $proceed = true; } } if($proceed == false){ trigger_error('User connection denied from: ' . $clientIp, E_USER_WARNING); if($ip_silent == false){ fm_set_msg(lng('Access denied. IP restriction applicable'), 'error'); fm_show_header_login(); fm_show_message(); } exit(); } } // Checking if the user is logged in or not. If not, it will show the login form. if ($use_auth) { if (isset($_SESSION[FM_SESSION_ID]['logged'], $auth_users[$_SESSION[FM_SESSION_ID]['logged']])) { // Logged } elseif (isset($_POST['fm_usr'], $_POST['fm_pwd'], $_POST['token'])) { // Logging In sleep(1); if(function_exists('password_verify')) { if (isset($auth_users[$_POST['fm_usr']]) && isset($_POST['fm_pwd']) && password_verify($_POST['fm_pwd'], $auth_users[$_POST['fm_usr']]) && verifyToken($_POST['token'])) { $_SESSION[FM_SESSION_ID]['logged'] = $_POST['fm_usr']; fm_set_msg(lng('You are logged in')); fm_redirect(FM_SELF_URL); } else { unset($_SESSION[FM_SESSION_ID]['logged']); fm_set_msg(lng('Login failed. Invalid username or password'), 'error'); fm_redirect(FM_SELF_URL); } } else { fm_set_msg(lng('password_hash not supported, Upgrade PHP version'), 'error');; } } else { // Form unset($_SESSION[FM_SESSION_ID]['logged']); fm_show_header_login(); ?>
".lng('Root path')." \"{$root_path}\" ".lng('not found!')." "; exit; } defined('FM_SHOW_HIDDEN') || define('FM_SHOW_HIDDEN', $show_hidden_files); defined('FM_ROOT_PATH') || define('FM_ROOT_PATH', $root_path); defined('FM_LANG') || define('FM_LANG', $lang); defined('FM_FILE_EXTENSION') || define('FM_FILE_EXTENSION', $allowed_file_extensions); defined('FM_UPLOAD_EXTENSION') || define('FM_UPLOAD_EXTENSION', $allowed_upload_extensions); defined('FM_EXCLUDE_ITEMS') || define('FM_EXCLUDE_ITEMS', (version_compare(PHP_VERSION, '7.0.0', '<') ? serialize($exclude_items) : $exclude_items)); defined('FM_DOC_VIEWER') || define('FM_DOC_VIEWER', $online_viewer); define('FM_READONLY', $global_readonly || ($use_auth && !empty($readonly_users) && isset($_SESSION[FM_SESSION_ID]['logged']) && in_array($_SESSION[FM_SESSION_ID]['logged'], $readonly_users))); define('FM_IS_WIN', DIRECTORY_SEPARATOR == '\\'); // always use ?p= if (!isset($_GET['p']) && empty($_FILES)) { fm_redirect(FM_SELF_URL . '?p='); } // get path $p = isset($_GET['p']) ? $_GET['p'] : (isset($_POST['p']) ? $_POST['p'] : ''); // clean path $p = fm_clean_path($p); // for ajax request - save $input = file_get_contents('php://input'); $_POST = (strpos($input, 'ajax') != FALSE && strpos($input, 'save') != FALSE) ? json_decode($input, true) : $_POST; // instead globals vars define('FM_PATH', $p); define('FM_USE_AUTH', $use_auth); define('FM_EDIT_FILE', $edit_files); defined('FM_ICONV_INPUT_ENC') || define('FM_ICONV_INPUT_ENC', $iconv_input_encoding); defined('FM_USE_HIGHLIGHTJS') || define('FM_USE_HIGHLIGHTJS', $use_highlightjs); defined('FM_HIGHLIGHTJS_STYLE') || define('FM_HIGHLIGHTJS_STYLE', $highlightjs_style); defined('FM_DATETIME_FORMAT') || define('FM_DATETIME_FORMAT', $datetime_format); unset($p, $use_auth, $iconv_input_encoding, $use_highlightjs, $highlightjs_style); /*************************** ACTIONS ***************************/ // Handle all AJAX Request if ((isset($_SESSION[FM_SESSION_ID]['logged'], $auth_users[$_SESSION[FM_SESSION_ID]['logged']]) || !FM_USE_AUTH) && isset($_POST['ajax'], $_POST['token']) && !FM_READONLY) { if(!verifyToken($_POST['token'])) { header('HTTP/1.0 401 Unauthorized'); die("Invalid Token."); } //search : get list of files from the current folder if(isset($_POST['type']) && $_POST['type']=="search") { $dir = $_POST['path'] == "." ? '': $_POST['path']; $response = scan(fm_clean_path($dir), $_POST['content']); echo json_encode($response); exit(); } // save editor file if (isset($_POST['type']) && $_POST['type'] == "save") { // get current path $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } // check path if (!is_dir($path)) { fm_redirect(FM_SELF_URL . '?p='); } $file = $_GET['edit']; $file = fm_clean_path($file); $file = str_replace('/', '', $file); if ($file == '' || !is_file($path . '/' . $file)) { fm_set_msg(lng('File not found'), 'error'); $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH)); } header('X-XSS-Protection:0'); $file_path = $path . '/' . $file; $writedata = $_POST['content']; $fd = fopen($file_path, "w"); $write_results = @fwrite($fd, $writedata); fclose($fd); if ($write_results === false){ header("HTTP/1.1 500 Internal Server Error"); die("Could Not Write File! - Check Permissions / Ownership"); } die(true); } // backup files if (isset($_POST['type']) && $_POST['type'] == "backup" && !empty($_POST['file'])) { $fileName = fm_clean_path($_POST['file']); $fullPath = FM_ROOT_PATH . '/'; if (!empty($_POST['path'])) { $relativeDirPath = fm_clean_path($_POST['path']); $fullPath .= "{$relativeDirPath}/"; } $date = date("dMy-His"); $newFileName = "{$fileName}-{$date}.bak"; $fullyQualifiedFileName = $fullPath . $fileName; try { if (!file_exists($fullyQualifiedFileName)) { throw new Exception("File {$fileName} not found"); } if (copy($fullyQualifiedFileName, $fullPath . $newFileName)) { echo "Backup {$newFileName} created"; } else { throw new Exception("Could not copy file {$fileName}"); } } catch (Exception $e) { echo $e->getMessage(); } } // Save Config if (isset($_POST['type']) && $_POST['type'] == "settings") { global $cfg, $lang, $report_errors, $show_hidden_files, $lang_list, $hide_Cols, $theme; $newLng = $_POST['js-language']; fm_get_translations([]); if (!array_key_exists($newLng, $lang_list)) { $newLng = 'en'; } $erp = isset($_POST['js-error-report']) && $_POST['js-error-report'] == "true" ? true : false; $shf = isset($_POST['js-show-hidden']) && $_POST['js-show-hidden'] == "true" ? true : false; $hco = isset($_POST['js-hide-cols']) && $_POST['js-hide-cols'] == "true" ? true : false; $te3 = $_POST['js-theme-3']; if ($cfg->data['lang'] != $newLng) { $cfg->data['lang'] = $newLng; $lang = $newLng; } if ($cfg->data['error_reporting'] != $erp) { $cfg->data['error_reporting'] = $erp; $report_errors = $erp; } if ($cfg->data['show_hidden'] != $shf) { $cfg->data['show_hidden'] = $shf; $show_hidden_files = $shf; } if ($cfg->data['show_hidden'] != $shf) { $cfg->data['show_hidden'] = $shf; $show_hidden_files = $shf; } if ($cfg->data['hide_Cols'] != $hco) { $cfg->data['hide_Cols'] = $hco; $hide_Cols = $hco; } if ($cfg->data['theme'] != $te3) { $cfg->data['theme'] = $te3; $theme = $te3; } $cfg->save(); echo true; } // new password hash if (isset($_POST['type']) && $_POST['type'] == "pwdhash") { $res = isset($_POST['inputPassword2']) && !empty($_POST['inputPassword2']) ? password_hash($_POST['inputPassword2'], PASSWORD_DEFAULT) : ''; echo $res; } //upload using url if(isset($_POST['type']) && $_POST['type'] == "upload" && !empty($_REQUEST["uploadurl"])) { $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } function event_callback ($message) { global $callback; echo json_encode($message); } function get_file_path () { global $path, $fileinfo, $temp_file; return $path."/".basename($fileinfo->name); } $url = !empty($_REQUEST["uploadurl"]) && preg_match("|^http(s)?://.+$|", stripslashes($_REQUEST["uploadurl"])) ? stripslashes($_REQUEST["uploadurl"]) : null; //prevent 127.* domain and known ports $domain = parse_url($url, PHP_URL_HOST); $port = parse_url($url, PHP_URL_PORT); $knownPorts = [22, 23, 25, 3306]; if (preg_match("/^localhost$|^127(?:\.[0-9]+){0,2}\.[0-9]+$|^(?:0*\:)*?:?0*1$/i", $domain) || in_array($port, $knownPorts)) { $err = array("message" => "URL is not allowed"); event_callback(array("fail" => $err)); exit(); } $use_curl = false; $temp_file = tempnam(sys_get_temp_dir(), "upload-"); $fileinfo = new stdClass(); $fileinfo->name = trim(urldecode(basename($url)), ".\x00..\x20"); $allowed = (FM_UPLOAD_EXTENSION) ? explode(',', FM_UPLOAD_EXTENSION) : false; $ext = strtolower(pathinfo($fileinfo->name, PATHINFO_EXTENSION)); $isFileAllowed = ($allowed) ? in_array($ext, $allowed) : true; $err = false; if(!$isFileAllowed) { $err = array("message" => "File extension is not allowed"); event_callback(array("fail" => $err)); exit(); } if (!$url) { $success = false; } else if ($use_curl) { @$fp = fopen($temp_file, "w"); @$ch = curl_init($url); curl_setopt($ch, CURLOPT_NOPROGRESS, false ); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); curl_setopt($ch, CURLOPT_FILE, $fp); @$success = curl_exec($ch); $curl_info = curl_getinfo($ch); if (!$success) { $err = array("message" => curl_error($ch)); } @curl_close($ch); fclose($fp); $fileinfo->size = $curl_info["size_download"]; $fileinfo->type = $curl_info["content_type"]; } else { $ctx = stream_context_create(); @$success = copy($url, $temp_file, $ctx); if (!$success) { $err = error_get_last(); } } if ($success) { $success = rename($temp_file, strtok(get_file_path(), '?')); } if ($success) { event_callback(array("done" => $fileinfo)); } else { unlink($temp_file); if (!$err) { $err = array("message" => "Invalid url parameter"); } event_callback(array("fail" => $err)); } } exit(); } // Delete file / folder if (isset($_GET['del'], $_POST['token']) && !FM_READONLY) { $del = str_replace( '/', '', fm_clean_path( $_GET['del'] ) ); if ($del != '' && $del != '..' && $del != '.' && verifyToken($_POST['token'])) { $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } $is_dir = is_dir($path . '/' . $del); if (fm_rdelete($path . '/' . $del)) { $msg = $is_dir ? lng('Folder').' %s '.lng('Deleted') : lng('File').' %s '.lng('Deleted'); fm_set_msg(sprintf($msg, fm_enc($del))); } else { $msg = $is_dir ? lng('Folder').' %s '.lng('not deleted') : lng('File').' %s '.lng('not deleted'); fm_set_msg(sprintf($msg, fm_enc($del)), 'error'); } } else { fm_set_msg(lng('Invalid file or folder name'), 'error'); } $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH)); } // Create a new file/folder if (isset($_POST['newfilename'], $_POST['newfile'], $_POST['token']) && !FM_READONLY) { $type = urldecode($_POST['newfile']); $new = str_replace( '/', '', fm_clean_path( strip_tags( $_POST['newfilename'] ) ) ); if (fm_isvalid_filename($new) && $new != '' && $new != '..' && $new != '.' && verifyToken($_POST['token'])) { $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } if ($type == "file") { if (!file_exists($path . '/' . $new)) { if(fm_is_valid_ext($new)) { @fopen($path . '/' . $new, 'w') or die('Cannot open file: ' . $new); fm_set_msg(sprintf(lng('File').' %s '.lng('Created'), fm_enc($new))); } else { fm_set_msg(lng('File extension is not allowed'), 'error'); } } else { fm_set_msg(sprintf(lng('File').' %s '.lng('already exists'), fm_enc($new)), 'alert'); } } else { if (fm_mkdir($path . '/' . $new, false) === true) { fm_set_msg(sprintf(lng('Folder').' %s '.lng('Created'), $new)); } elseif (fm_mkdir($path . '/' . $new, false) === $path . '/' . $new) { fm_set_msg(sprintf(lng('Folder').' %s '.lng('already exists'), fm_enc($new)), 'alert'); } else { fm_set_msg(sprintf(lng('Folder').' %s '.lng('not created'), fm_enc($new)), 'error'); } } } else { fm_set_msg(lng('Invalid characters in file or folder name'), 'error'); } $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH)); } // Copy folder / file if (isset($_GET['copy'], $_GET['finish']) && !FM_READONLY) { // from $copy = urldecode($_GET['copy']); $copy = fm_clean_path($copy); // empty path if ($copy == '') { fm_set_msg(lng('Source path not defined'), 'error'); $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH)); } // abs path from $from = FM_ROOT_PATH . '/' . $copy; // abs path to $dest = FM_ROOT_PATH; if (FM_PATH != '') { $dest .= '/' . FM_PATH; } $dest .= '/' . basename($from); // move? $move = isset($_GET['move']); $move = fm_clean_path(urldecode($move)); // copy/move/duplicate if ($from != $dest) { $msg_from = trim(FM_PATH . '/' . basename($from), '/'); if ($move) { // Move and to != from so just perform move $rename = fm_rename($from, $dest); if ($rename) { fm_set_msg(sprintf(lng('Moved from').' %s '.lng('to').' %s', fm_enc($copy), fm_enc($msg_from))); } elseif ($rename === null) { fm_set_msg(lng('File or folder with this path already exists'), 'alert'); } else { fm_set_msg(sprintf(lng('Error while moving from').' %s '.lng('to').' %s', fm_enc($copy), fm_enc($msg_from)), 'error'); } } else { // Not move and to != from so copy with original name if (fm_rcopy($from, $dest)) { fm_set_msg(sprintf(lng('Copied from').' %s '.lng('to').' %s', fm_enc($copy), fm_enc($msg_from))); } else { fm_set_msg(sprintf(lng('Error while copying from').' %s '.lng('to').' %s', fm_enc($copy), fm_enc($msg_from)), 'error'); } } } else { if (!$move){ //Not move and to = from so duplicate $msg_from = trim(FM_PATH . '/' . basename($from), '/'); $fn_parts = pathinfo($from); $extension_suffix = ''; if(!is_dir($from)){ $extension_suffix = '.'.$fn_parts['extension']; } //Create new name for duplicate $fn_duplicate = $fn_parts['dirname'].'/'.$fn_parts['filename'].'-'.date('YmdHis').$extension_suffix; $loop_count = 0; $max_loop = 1000; // Check if a file with the duplicate name already exists, if so, make new name (edge case...) while(file_exists($fn_duplicate) & $loop_count < $max_loop){ $fn_parts = pathinfo($fn_duplicate); $fn_duplicate = $fn_parts['dirname'].'/'.$fn_parts['filename'].'-copy'.$extension_suffix; $loop_count++; } if (fm_rcopy($from, $fn_duplicate, False)) { fm_set_msg(sprintf('Copied from %s to %s', fm_enc($copy), fm_enc($fn_duplicate))); } else { fm_set_msg(sprintf('Error while copying from %s to %s', fm_enc($copy), fm_enc($fn_duplicate)), 'error'); } } else{ fm_set_msg(lng('Paths must be not equal'), 'alert'); } } $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH)); } // Mass copy files/ folders if (isset($_POST['file'], $_POST['copy_to'], $_POST['finish'], $_POST['token']) && !FM_READONLY) { if(!verifyToken($_POST['token'])) { fm_set_msg(lng('Invalid Token.'), 'error'); } // from $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } // to $copy_to_path = FM_ROOT_PATH; $copy_to = fm_clean_path($_POST['copy_to']); if ($copy_to != '') { $copy_to_path .= '/' . $copy_to; } if ($path == $copy_to_path) { fm_set_msg(lng('Paths must be not equal'), 'alert'); $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH)); } if (!is_dir($copy_to_path)) { if (!fm_mkdir($copy_to_path, true)) { fm_set_msg('Unable to create destination folder', 'error'); $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH)); } } // move? $move = isset($_POST['move']); // copy/move $errors = 0; $files = $_POST['file']; if (is_array($files) && count($files)) { foreach ($files as $f) { if ($f != '') { $f = fm_clean_path($f); // abs path from $from = $path . '/' . $f; // abs path to $dest = $copy_to_path . '/' . $f; // do if ($move) { $rename = fm_rename($from, $dest); if ($rename === false) { $errors++; } } else { if (!fm_rcopy($from, $dest)) { $errors++; } } } } if ($errors == 0) { $msg = $move ? 'Selected files and folders moved' : 'Selected files and folders copied'; fm_set_msg($msg); } else { $msg = $move ? 'Error while moving items' : 'Error while copying items'; fm_set_msg($msg, 'error'); } } else { fm_set_msg(lng('Nothing selected'), 'alert'); } $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH)); } // Rename if (isset($_POST['rename_from'], $_POST['rename_to'], $_POST['token']) && !FM_READONLY) { if(!verifyToken($_POST['token'])) { fm_set_msg("Invalid Token.", 'error'); } // old name $old = urldecode($_POST['rename_from']); $old = fm_clean_path($old); $old = str_replace('/', '', $old); // new name $new = urldecode($_POST['rename_to']); $new = fm_clean_path(strip_tags($new)); $new = str_replace('/', '', $new); // path $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } // rename if (fm_isvalid_filename($new) && $old != '' && $new != '') { if (fm_rename($path . '/' . $old, $path . '/' . $new)) { fm_set_msg(sprintf(lng('Renamed from').' %s '. lng('to').' %s', fm_enc($old), fm_enc($new))); } else { fm_set_msg(sprintf(lng('Error while renaming from').' %s '. lng('to').' %s', fm_enc($old), fm_enc($new)), 'error'); } } else { fm_set_msg(lng('Invalid characters in file name'), 'error'); } $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH)); } // Download if (isset($_GET['dl'], $_POST['token'])) { if(!verifyToken($_POST['token'])) { fm_set_msg("Invalid Token.", 'error'); } $dl = urldecode($_GET['dl']); $dl = fm_clean_path($dl); $dl = str_replace('/', '', $dl); $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } if ($dl != '' && is_file($path . '/' . $dl)) { fm_download_file($path . '/' . $dl, $dl, 1024); exit; } else { fm_set_msg(lng('File not found'), 'error'); $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH)); } } // Upload if (!empty($_FILES) && !FM_READONLY) { if(isset($_POST['token'])) { if(!verifyToken($_POST['token'])) { $response = array ('status' => 'error','info' => "Invalid Token."); echo json_encode($response); exit(); } } else { $response = array ('status' => 'error','info' => "Token Missing."); echo json_encode($response); exit(); } $chunkIndex = $_POST['dzchunkindex']; $chunkTotal = $_POST['dztotalchunkcount']; $fullPathInput = fm_clean_path($_REQUEST['fullpath']); $f = $_FILES; $path = FM_ROOT_PATH; $ds = DIRECTORY_SEPARATOR; if (FM_PATH != '') { $path .= '/' . FM_PATH; } $errors = 0; $uploads = 0; $allowed = (FM_UPLOAD_EXTENSION) ? explode(',', FM_UPLOAD_EXTENSION) : false; $response = array ( 'status' => 'error', 'info' => 'Oops! Try again' ); $filename = $f['file']['name']; $tmp_name = $f['file']['tmp_name']; $ext = pathinfo($filename, PATHINFO_FILENAME) != '' ? strtolower(pathinfo($filename, PATHINFO_EXTENSION)) : ''; $isFileAllowed = ($allowed) ? in_array($ext, $allowed) : true; if(!fm_isvalid_filename($filename) && !fm_isvalid_filename($fullPathInput)) { $response = array ( 'status' => 'error', 'info' => "Invalid File name!", ); echo json_encode($response); exit(); } $targetPath = $path . $ds; if ( is_writable($targetPath) ) { $fullPath = $path . '/' . $fullPathInput; $folder = substr($fullPath, 0, strrpos($fullPath, "/")); if (!is_dir($folder)) { $old = umask(0); mkdir($folder, 0777, true); umask($old); } if (empty($f['file']['error']) && !empty($tmp_name) && $tmp_name != 'none' && $isFileAllowed) { if ($chunkTotal){ $out = @fopen("{$fullPath}.part", $chunkIndex == 0 ? "wb" : "ab"); if ($out) { $in = @fopen($tmp_name, "rb"); if ($in) { if (PHP_VERSION_ID < 80009) { // workaround https://bugs.php.net/bug.php?id=81145 do { for (;;) { $buff = fread($in, 4096); if ($buff === false || $buff === '') { break; } fwrite($out, $buff); } } while (!feof($in)); } else { stream_copy_to_stream($in, $out); } $response = array ( 'status' => 'success', 'info' => "file upload successful" ); } else { $response = array ( 'status' => 'error', 'info' => "failed to open output stream", 'errorDetails' => error_get_last() ); } @fclose($in); @fclose($out); @unlink($tmp_name); $response = array ( 'status' => 'success', 'info' => "file upload successful" ); } else { $response = array ( 'status' => 'error', 'info' => "failed to open output stream" ); } if ($chunkIndex == $chunkTotal - 1) { if (file_exists ($fullPath)) { $ext_1 = $ext ? '.'.$ext : ''; $fullPathTarget = $path . '/' . basename($fullPathInput, $ext_1) .'_'. date('ymdHis'). $ext_1; } else { $fullPathTarget = $fullPath; } rename("{$fullPath}.part", $fullPathTarget); } } else if (move_uploaded_file($tmp_name, $fullPath)) { // Be sure that the file has been uploaded if ( file_exists($fullPath) ) { $response = array ( 'status' => 'success', 'info' => "file upload successful" ); } else { $response = array ( 'status' => 'error', 'info' => 'Couldn\'t upload the requested file.' ); } } else { $response = array ( 'status' => 'error', 'info' => "Error while uploading files. Uploaded files $uploads", ); } } } else { $response = array ( 'status' => 'error', 'info' => 'The specified folder for upload isn\'t writeable.' ); } // Return the response echo json_encode($response); exit(); } // Mass deleting if (isset($_POST['group'], $_POST['delete'], $_POST['token']) && !FM_READONLY) { if(!verifyToken($_POST['token'])) { fm_set_msg(lng("Invalid Token."), 'error'); } $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } $errors = 0; $files = $_POST['file']; if (is_array($files) && count($files)) { foreach ($files as $f) { if ($f != '') { $new_path = $path . '/' . $f; if (!fm_rdelete($new_path)) { $errors++; } } } if ($errors == 0) { fm_set_msg(lng('Selected files and folder deleted')); } else { fm_set_msg(lng('Error while deleting items'), 'error'); } } else { fm_set_msg(lng('Nothing selected'), 'alert'); } $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH)); } // Pack files zip, tar if (isset($_POST['group'], $_POST['token']) && (isset($_POST['zip']) || isset($_POST['tar'])) && !FM_READONLY) { if(!verifyToken($_POST['token'])) { fm_set_msg(lng("Invalid Token."), 'error'); } $path = FM_ROOT_PATH; $ext = 'zip'; if (FM_PATH != '') { $path .= '/' . FM_PATH; } //set pack type $ext = isset($_POST['tar']) ? 'tar' : 'zip'; if (($ext == "zip" && !class_exists('ZipArchive')) || ($ext == "tar" && !class_exists('PharData'))) { fm_set_msg(lng('Operations with archives are not available'), 'error'); $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH)); } $files = $_POST['file']; $sanitized_files = array(); // clean path foreach($files as $file){ array_push($sanitized_files, fm_clean_path($file)); } $files = $sanitized_files; if (!empty($files)) { chdir($path); if (count($files) == 1) { $one_file = reset($files); $one_file = basename($one_file); $zipname = $one_file . '_' . date('ymd_His') . '.'.$ext; } else { $zipname = 'archive_' . date('ymd_His') . '.'.$ext; } if($ext == 'zip') { $zipper = new FM_Zipper(); $res = $zipper->create($zipname, $files); } elseif ($ext == 'tar') { $tar = new FM_Zipper_Tar(); $res = $tar->create($zipname, $files); } if ($res) { fm_set_msg(sprintf(lng('Archive').' %s '.lng('Created'), fm_enc($zipname))); } else { fm_set_msg(lng('Archive not created'), 'error'); } } else { fm_set_msg(lng('Nothing selected'), 'alert'); } $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH)); } // Unpack zip, tar if (isset($_POST['unzip'], $_POST['token']) && !FM_READONLY) { if(!verifyToken($_POST['token'])) { fm_set_msg(lng("Invalid Token."), 'error'); } $unzip = urldecode($_POST['unzip']); $unzip = fm_clean_path($unzip); $unzip = str_replace('/', '', $unzip); $isValid = false; $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } if ($unzip != '' && is_file($path . '/' . $unzip)) { $zip_path = $path . '/' . $unzip; $ext = pathinfo($zip_path, PATHINFO_EXTENSION); $isValid = true; } else { fm_set_msg(lng('File not found'), 'error'); } if (($ext == "zip" && !class_exists('ZipArchive')) || ($ext == "tar" && !class_exists('PharData'))) { fm_set_msg(lng('Operations with archives are not available'), 'error'); $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH)); } if ($isValid) { //to folder $tofolder = ''; if (isset($_POST['tofolder'])) { $tofolder = pathinfo($zip_path, PATHINFO_FILENAME); if (fm_mkdir($path . '/' . $tofolder, true)) { $path .= '/' . $tofolder; } } if($ext == "zip") { $zipper = new FM_Zipper(); $res = $zipper->unzip($zip_path, $path); } elseif ($ext == "tar") { try { $gzipper = new PharData($zip_path); if (@$gzipper->extractTo($path,null, true)) { $res = true; } else { $res = false; } } catch (Exception $e) { //TODO:: need to handle the error $res = true; } } if ($res) { fm_set_msg(lng('Archive unpacked')); } else { fm_set_msg(lng('Archive not unpacked'), 'error'); } } else { fm_set_msg(lng('File not found'), 'error'); } $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH)); } // Change Perms (not for Windows) if (isset($_POST['chmod'], $_POST['token']) && !FM_READONLY && !FM_IS_WIN) { if(!verifyToken($_POST['token'])) { fm_set_msg(lng("Invalid Token."), 'error'); } $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } $file = $_POST['chmod']; $file = fm_clean_path($file); $file = str_replace('/', '', $file); if ($file == '' || (!is_file($path . '/' . $file) && !is_dir($path . '/' . $file))) { fm_set_msg(lng('File not found'), 'error'); $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH)); } $mode = 0; if (!empty($_POST['ur'])) { $mode |= 0400; } if (!empty($_POST['uw'])) { $mode |= 0200; } if (!empty($_POST['ux'])) { $mode |= 0100; } if (!empty($_POST['gr'])) { $mode |= 0040; } if (!empty($_POST['gw'])) { $mode |= 0020; } if (!empty($_POST['gx'])) { $mode |= 0010; } if (!empty($_POST['or'])) { $mode |= 0004; } if (!empty($_POST['ow'])) { $mode |= 0002; } if (!empty($_POST['ox'])) { $mode |= 0001; } if (@chmod($path . '/' . $file, $mode)) { fm_set_msg(lng('Permissions changed')); } else { fm_set_msg(lng('Permissions not changed'), 'error'); } $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH)); } /*************************** ACTIONS ***************************/ // get current path $path = FM_ROOT_PATH; if (FM_PATH != '') { $path .= '/' . FM_PATH; } // check path if (!is_dir($path)) { fm_redirect(FM_SELF_URL . '?p='); } // get parent folder $parent = fm_get_parent_path(FM_PATH); $objects = is_readable($path) ? scandir($path) : array(); $folders = array(); $files = array(); $current_path = array_slice(explode("/",$path), -1)[0]; if (is_array($objects) && fm_is_exclude_items($current_path)) { foreach ($objects as $file) { if ($file == '.' || $file == '..') { continue; } if (!FM_SHOW_HIDDEN && substr($file, 0, 1) === '.') { continue; } $new_path = $path . '/' . $file; if (@is_file($new_path) && fm_is_exclude_items($file)) { $files[] = $file; } elseif (@is_dir($new_path) && $file != '.' && $file != '..' && fm_is_exclude_items($file)) { $folders[] = $file; } } } if (!empty($files)) { natcasesort($files); } if (!empty($folders)) { natcasesort($folders); } // upload form if (isset($_GET['upload']) && !FM_READONLY) { fm_show_header(); // HEADER fm_show_nav_path(FM_PATH); // current path //get the allowed file extensions function getUploadExt() { $extArr = explode(',', FM_UPLOAD_EXTENSION); if(FM_UPLOAD_EXTENSION && $extArr) { array_walk($extArr, function(&$x) {$x = ".$x";}); return implode(',', $extArr); } return ''; } ?>
' . PHP_EOL; } ?>

: , ', $copy_files) ?>

:
/

 

Copying

Source path:
Destination folder:

Copy   Move   Cancel

/>
/>
/>

""

:
File size:
MIME-type:
:
:
:
: %
'.lng('Image size').': ' . (isset($image_size[0]) ? $image_size[0] : '0') . ' x ' . (isset($image_size[1]) ? $image_size[1] : '0') . '
'; } // Text info if ($is_text) { $is_utf8 = fm_is_utf8($content); if (function_exists('iconv')) { if (!$is_utf8) { $content = iconv(FM_ICONV_INPUT_ENC, 'UTF-8//IGNORE', $content); } } echo ''.lng('Charset').': ' . ($is_utf8 ? 'utf-8' : '8 bit') . '
'; } ?>

 
 
     
'; } else if($online_viewer == 'microsoft') { echo ''; } } elseif ($is_zip) { // ZIP content if ($filenames !== false) { echo ''; foreach ($filenames as $fn) { if ($fn['folder']) { echo '' . fm_enc($fn['name']) . '
'; } else { echo $fn['name'] . ' (' . fm_get_filesize($fn['filesize']) . ')
'; } } echo '
'; } else { echo '

'.lng('Error while fetching archive info').'

'; } } elseif ($is_image) { // Image content if (in_array($ext, array('gif', 'jpg', 'jpeg', 'png', 'bmp', 'ico', 'svg', 'webp', 'avif'))) { echo '

'; } } elseif ($is_audio) { // Audio content echo '

'; } elseif ($is_video) { // Video content echo '
'; } elseif ($is_text) { if (FM_USE_HIGHLIGHTJS) { // highlight $hljs_classes = array( 'shtml' => 'xml', 'htaccess' => 'apache', 'phtml' => 'php', 'lock' => 'json', 'svg' => 'xml', ); $hljs_class = isset($hljs_classes[$ext]) ? 'lang-' . $hljs_classes[$ext] : 'lang-' . $ext; if (empty($ext) || in_array(strtolower($file), fm_get_text_names()) || preg_match('#\.min\.(css|js)$#i', $file)) { $hljs_class = 'nohighlight'; } $content = '
' . fm_enc($content) . '
'; } elseif (in_array($ext, array('php', 'php4', 'php5', 'phtml', 'phps'))) { // php highlight $content = highlight_string($content, true); } else { $content = '
' . fm_enc($content) . '
'; } echo $content; } ?>
'. $file. ''; header('X-XSS-Protection:0'); fm_show_header(); // HEADER fm_show_nav_path(FM_PATH); // current path $file_url = FM_ROOT_URL . fm_convert_win((FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $file); $file_path = $path . '/' . $file; // normal editer $isNormalEditor = true; if (isset($_GET['env'])) { if ($_GET['env'] == "ace") { $isNormalEditor = false; } } // Save File if (isset($_POST['savedata'])) { $writedata = $_POST['savedata']; $fd = fopen($file_path, "w"); @fwrite($fd, $writedata); fclose($fd); fm_set_msg(lng('File Saved Successfully')); } $ext = strtolower(pathinfo($file_path, PATHINFO_EXTENSION)); $mime_type = fm_get_mime_type($file_path); $filesize = filesize($file_path); $is_text = false; $content = ''; // for text if (in_array($ext, fm_get_text_exts()) || substr($mime_type, 0, 4) == 'text' || in_array($mime_type, fm_get_text_mimes())) { $is_text = true; $content = file_get_contents($file_path); } ?>
' . htmlspecialchars($content) . ''; echo ''; } elseif ($is_text) { echo '
' . htmlspecialchars($content) . '
'; } else { fm_set_msg(lng('FILE EXTENSION HAS NOT SUPPORTED'), 'error'); } ?>

:

 

'?'); } if ($group === false) { $group = array('name' => '?'); } } else { $owner = array('name' => '?'); $group = array('name' => '?'); } ?> '?'); } if ($group === false) { $group = array('name' => '?'); } } else { $owner = array('name' => '?'); $group = array('name' => '?'); } ?>
..
>
' . readlink($path . '/' . $f) . '' : '') ?>
">
>
' . readlink($path . '/' . $f) . '' : '') ?>
">
'.fm_get_filesize($all_files_size).'' ?> '.$num_files.'' ?> '.$num_folders.'' ?>
"; return; } echo "$external[$key]"; } /** * Verify CSRF TOKEN and remove after cerify * @param string $token * @return bool */ function verifyToken($token) { if (hash_equals($_SESSION['token'], $token)) { return true; } return false; } /** * Delete file or folder (recursively) * @param string $path * @return bool */ function fm_rdelete($path) { if (is_link($path)) { return unlink($path); } elseif (is_dir($path)) { $objects = scandir($path); $ok = true; if (is_array($objects)) { foreach ($objects as $file) { if ($file != '.' && $file != '..') { if (!fm_rdelete($path . '/' . $file)) { $ok = false; } } } } return ($ok) ? rmdir($path) : false; } elseif (is_file($path)) { return unlink($path); } return false; } /** * Recursive chmod * @param string $path * @param int $filemode * @param int $dirmode * @return bool * @todo Will use in mass chmod */ function fm_rchmod($path, $filemode, $dirmode) { if (is_dir($path)) { if (!chmod($path, $dirmode)) { return false; } $objects = scandir($path); if (is_array($objects)) { foreach ($objects as $file) { if ($file != '.' && $file != '..') { if (!fm_rchmod($path . '/' . $file, $filemode, $dirmode)) { return false; } } } } return true; } elseif (is_link($path)) { return true; } elseif (is_file($path)) { return chmod($path, $filemode); } return false; } /** * Check the file extension which is allowed or not * @param string $filename * @return bool */ function fm_is_valid_ext($filename) { $allowed = (FM_FILE_EXTENSION) ? explode(',', FM_FILE_EXTENSION) : false; $ext = pathinfo($filename, PATHINFO_EXTENSION); $isFileAllowed = ($allowed) ? in_array($ext, $allowed) : true; return ($isFileAllowed) ? true : false; } /** * Safely rename * @param string $old * @param string $new * @return bool|null */ function fm_rename($old, $new) { $isFileAllowed = fm_is_valid_ext($new); if(!is_dir($old)) { if (!$isFileAllowed) return false; } return (!file_exists($new) && file_exists($old)) ? rename($old, $new) : null; } /** * Copy file or folder (recursively). * @param string $path * @param string $dest * @param bool $upd Update files * @param bool $force Create folder with same names instead file * @return bool */ function fm_rcopy($path, $dest, $upd = true, $force = true) { if (is_dir($path)) { if (!fm_mkdir($dest, $force)) { return false; } $objects = scandir($path); $ok = true; if (is_array($objects)) { foreach ($objects as $file) { if ($file != '.' && $file != '..') { if (!fm_rcopy($path . '/' . $file, $dest . '/' . $file)) { $ok = false; } } } } return $ok; } elseif (is_file($path)) { return fm_copy($path, $dest, $upd); } return false; } /** * Safely create folder * @param string $dir * @param bool $force * @return bool */ function fm_mkdir($dir, $force) { if (file_exists($dir)) { if (is_dir($dir)) { return $dir; } elseif (!$force) { return false; } unlink($dir); } return mkdir($dir, 0777, true); } /** * Safely copy file * @param string $f1 * @param string $f2 * @param bool $upd Indicates if file should be updated with new content * @return bool */ function fm_copy($f1, $f2, $upd) { $time1 = filemtime($f1); if (file_exists($f2)) { $time2 = filemtime($f2); if ($time2 >= $time1 && $upd) { return false; } } $ok = copy($f1, $f2); if ($ok) { touch($f2, $time1); } return $ok; } /** * Get mime type * @param string $file_path * @return mixed|string */ function fm_get_mime_type($file_path) { if (function_exists('finfo_open')) { $finfo = finfo_open(FILEINFO_MIME_TYPE); $mime = finfo_file($finfo, $file_path); finfo_close($finfo); return $mime; } elseif (function_exists('mime_content_type')) { return mime_content_type($file_path); } elseif (!stristr(ini_get('disable_functions'), 'shell_exec')) { $file = escapeshellarg($file_path); $mime = shell_exec('file -bi ' . $file); return $mime; } else { return '--'; } } /** * HTTP Redirect * @param string $url * @param int $code */ function fm_redirect($url, $code = 302) { header('Location: ' . $url, true, $code); exit; } /** * Path traversal prevention and clean the url * It replaces (consecutive) occurrences of / and \\ with whatever is in DIRECTORY_SEPARATOR, and processes /. and /.. fine. * @param $path * @return string */ function get_absolute_path($path) { $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path); $parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen'); $absolutes = array(); foreach ($parts as $part) { if ('.' == $part) continue; if ('..' == $part) { array_pop($absolutes); } else { $absolutes[] = $part; } } return implode(DIRECTORY_SEPARATOR, $absolutes); } /** * Clean path * @param string $path * @return string */ function fm_clean_path($path, $trim = true) { $path = $trim ? trim($path) : $path; $path = trim($path, '\\/'); $path = str_replace(array('../', '..\\'), '', $path); $path = get_absolute_path($path); if ($path == '..') { $path = ''; } return str_replace('\\', '/', $path); } /** * Get parent path * @param string $path * @return bool|string */ function fm_get_parent_path($path) { $path = fm_clean_path($path); if ($path != '') { $array = explode('/', $path); if (count($array) > 1) { $array = array_slice($array, 0, -1); return implode('/', $array); } return ''; } return false; } function fm_get_display_path($file_path) { global $path_display_mode, $root_path, $root_url; switch ($path_display_mode) { case 'relative': return array( 'label' => 'Path', 'path' => fm_enc(fm_convert_win(str_replace($root_path, '', $file_path))) ); case 'host': $relative_path = str_replace($root_path, '', $file_path); return array( 'label' => 'Host Path', 'path' => fm_enc(fm_convert_win('/' . $root_url . '/' . ltrim(str_replace('\\', '/', $relative_path), '/'))) ); case 'full': default: return array( 'label' => 'Full Path', 'path' => fm_enc(fm_convert_win($file_path)) ); } } /** * Check file is in exclude list * @param string $file * @return bool */ function fm_is_exclude_items($file) { $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION)); if (isset($exclude_items) and sizeof($exclude_items)) { unset($exclude_items); } $exclude_items = FM_EXCLUDE_ITEMS; if (version_compare(PHP_VERSION, '7.0.0', '<')) { $exclude_items = unserialize($exclude_items); } if (!in_array($file, $exclude_items) && !in_array("*.$ext", $exclude_items)) { return true; } return false; } /** * get language translations from json file * @param int $tr * @return array */ function fm_get_translations($tr) { try { $content = @file_get_contents('translation.json'); if($content !== FALSE) { $lng = json_decode($content, TRUE); global $lang_list; foreach ($lng["language"] as $key => $value) { $code = $value["code"]; $lang_list[$code] = $value["name"]; if ($tr) $tr[$code] = $value["translation"]; } return $tr; } } catch (Exception $e) { echo $e; } } /** * @param string $file * Recover all file sizes larger than > 2GB. * Works on php 32bits and 64bits and supports linux * @return int|string */ function fm_get_size($file) { static $iswin; static $isdarwin; if (!isset($iswin)) { $iswin = (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'); } if (!isset($isdarwin)) { $isdarwin = (strtoupper(substr(PHP_OS, 0)) == "DARWIN"); } static $exec_works; if (!isset($exec_works)) { $exec_works = (function_exists('exec') && !ini_get('safe_mode') && @exec('echo EXEC') == 'EXEC'); } // try a shell command if ($exec_works) { $arg = escapeshellarg($file); $cmd = ($iswin) ? "for %F in (\"$file\") do @echo %~zF" : ($isdarwin ? "stat -f%z $arg" : "stat -c%s $arg"); @exec($cmd, $output); if (is_array($output) && ctype_digit($size = trim(implode("\n", $output)))) { return $size; } } // try the Windows COM interface if ($iswin && class_exists("COM")) { try { $fsobj = new COM('Scripting.FileSystemObject'); $f = $fsobj->GetFile( realpath($file) ); $size = $f->Size; } catch (Exception $e) { $size = null; } if (ctype_digit($size)) { return $size; } } // if all else fails return filesize($file); } /** * Get nice filesize * @param int $size * @return string */ function fm_get_filesize($size) { $size = (float) $size; $units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'); $power = ($size > 0) ? floor(log($size, 1024)) : 0; $power = ($power > (count($units) - 1)) ? (count($units) - 1) : $power; return sprintf('%s %s', round($size / pow(1024, $power), 2), $units[$power]); } /** * Get total size of directory tree. * * @param string $directory Relative or absolute directory name. * @return int Total number of bytes. */ function fm_get_directorysize($directory) { $bytes = 0; $directory = realpath($directory); if ($directory !== false && $directory != '' && file_exists($directory)){ foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory, FilesystemIterator::SKIP_DOTS)) as $file){ $bytes += $file->getSize(); } } return $bytes; } /** * Get info about zip archive * @param string $path * @return array|bool */ function fm_get_zif_info($path, $ext) { if ($ext == 'zip' && function_exists('zip_open')) { $arch = @zip_open($path); if ($arch) { $filenames = array(); while ($zip_entry = @zip_read($arch)) { $zip_name = @zip_entry_name($zip_entry); $zip_folder = substr($zip_name, -1) == '/'; $filenames[] = array( 'name' => $zip_name, 'filesize' => @zip_entry_filesize($zip_entry), 'compressed_size' => @zip_entry_compressedsize($zip_entry), 'folder' => $zip_folder //'compression_method' => zip_entry_compressionmethod($zip_entry), ); } @zip_close($arch); return $filenames; } } elseif($ext == 'tar' && class_exists('PharData')) { $archive = new PharData($path); $filenames = array(); foreach(new RecursiveIteratorIterator($archive) as $file) { $parent_info = $file->getPathInfo(); $zip_name = str_replace("phar://".$path, '', $file->getPathName()); $zip_name = substr($zip_name, ($pos = strpos($zip_name, '/')) !== false ? $pos + 1 : 0); $zip_folder = $parent_info->getFileName(); $zip_info = new SplFileInfo($file); $filenames[] = array( 'name' => $zip_name, 'filesize' => $zip_info->getSize(), 'compressed_size' => $file->getCompressedSize(), 'folder' => $zip_folder ); } return $filenames; } return false; } /** * Encode html entities * @param string $text * @return string */ function fm_enc($text) { return htmlspecialchars($text, ENT_QUOTES, 'UTF-8'); } /** * Prevent XSS attacks * @param string $text * @return string */ function fm_isvalid_filename($text) { return (strpbrk($text, '/?%*:|"<>') === FALSE) ? true : false; } /** * Save message in session * @param string $msg * @param string $status */ function fm_set_msg($msg, $status = 'ok') { $_SESSION[FM_SESSION_ID]['message'] = $msg; $_SESSION[FM_SESSION_ID]['status'] = $status; } /** * Check if string is in UTF-8 * @param string $string * @return int */ function fm_is_utf8($string) { return preg_match('//u', $string); } /** * Convert file name to UTF-8 in Windows * @param string $filename * @return string */ function fm_convert_win($filename) { if (FM_IS_WIN && function_exists('iconv')) { $filename = iconv(FM_ICONV_INPUT_ENC, 'UTF-8//IGNORE', $filename); } return $filename; } /** * @param $obj * @return array */ function fm_object_to_array($obj) { if (!is_object($obj) && !is_array($obj)) { return $obj; } if (is_object($obj)) { $obj = get_object_vars($obj); } return array_map('fm_object_to_array', $obj); } /** * Get CSS classname for file * @param string $path * @return string */ function fm_get_file_icon_class($path) { // get extension $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION)); switch ($ext) { case 'ico': case 'gif': case 'jpg': case 'jpeg': case 'jpc': case 'jp2': case 'jpx': case 'xbm': case 'wbmp': case 'png': case 'bmp': case 'tif': case 'tiff': case 'webp': case 'avif': case 'svg': $img = 'fa fa-picture-o'; break; case 'passwd': case 'ftpquota': case 'sql': case 'js': case 'ts': case 'jsx': case 'tsx': case 'hbs': case 'json': case 'sh': case 'config': case 'twig': case 'tpl': case 'md': case 'gitignore': case 'c': case 'cpp': case 'cs': case 'py': case 'rs': case 'map': case 'lock': case 'dtd': $img = 'fa fa-file-code-o'; break; case 'txt': case 'ini': case 'conf': case 'log': case 'htaccess': case 'yaml': case 'yml': case 'toml': case 'tmp': case 'top': case 'bot': case 'dat': case 'bak': case 'htpasswd': case 'pl': $img = 'fa fa-file-text-o'; break; case 'css': case 'less': case 'sass': case 'scss': $img = 'fa fa-css3'; break; case 'bz2': case 'tbz2': case 'tbz': case 'zip': case 'rar': case 'gz': case 'tgz': case 'tar': case '7z': case 'xz': case 'txz': case 'zst': case 'tzst': $img = 'fa fa-file-archive-o'; break; case 'php': case 'php4': case 'php5': case 'phps': case 'phtml': $img = 'fa fa-code'; break; case 'htm': case 'html': case 'shtml': case 'xhtml': $img = 'fa fa-html5'; break; case 'xml': case 'xsl': $img = 'fa fa-file-excel-o'; break; case 'wav': case 'mp3': case 'mp2': case 'm4a': case 'aac': case 'ogg': case 'oga': case 'wma': case 'mka': case 'flac': case 'ac3': case 'tds': $img = 'fa fa-music'; break; case 'm3u': case 'm3u8': case 'pls': case 'cue': case 'xspf': $img = 'fa fa-headphones'; break; case 'avi': case 'mpg': case 'mpeg': case 'mp4': case 'm4v': case 'flv': case 'f4v': case 'ogm': case 'ogv': case 'mov': case 'mkv': case '3gp': case 'asf': case 'wmv': case 'webm': $img = 'fa fa-file-video-o'; break; case 'eml': case 'msg': $img = 'fa fa-envelope-o'; break; case 'xls': case 'xlsx': case 'ods': $img = 'fa fa-file-excel-o'; break; case 'csv': $img = 'fa fa-file-text-o'; break; case 'bak': case 'swp': $img = 'fa fa-clipboard'; break; case 'doc': case 'docx': case 'odt': $img = 'fa fa-file-word-o'; break; case 'ppt': case 'pptx': $img = 'fa fa-file-powerpoint-o'; break; case 'ttf': case 'ttc': case 'otf': case 'woff': case 'woff2': case 'eot': case 'fon': $img = 'fa fa-font'; break; case 'pdf': $img = 'fa fa-file-pdf-o'; break; case 'psd': case 'ai': case 'eps': case 'fla': case 'swf': $img = 'fa fa-file-image-o'; break; case 'exe': case 'msi': $img = 'fa fa-file-o'; break; case 'bat': $img = 'fa fa-terminal'; break; default: $img = 'fa fa-info-circle'; } return $img; } /** * Get image files extensions * @return array */ function fm_get_image_exts() { return array('ico', 'gif', 'jpg', 'jpeg', 'jpc', 'jp2', 'jpx', 'xbm', 'wbmp', 'png', 'bmp', 'tif', 'tiff', 'psd', 'svg', 'webp', 'avif'); } /** * Get video files extensions * @return array */ function fm_get_video_exts() { return array('avi', 'webm', 'wmv', 'mp4', 'm4v', 'ogm', 'ogv', 'mov', 'mkv'); } /** * Get audio files extensions * @return array */ function fm_get_audio_exts() { return array('wav', 'mp3', 'ogg', 'm4a'); } /** * Get text file extensions * @return array */ function fm_get_text_exts() { return array( 'txt', 'css', 'ini', 'conf', 'log', 'htaccess', 'passwd', 'ftpquota', 'sql', 'js', 'ts', 'jsx', 'tsx', 'mjs', 'json', 'sh', 'config', 'php', 'php4', 'php5', 'phps', 'phtml', 'htm', 'html', 'shtml', 'xhtml', 'xml', 'xsl', 'm3u', 'm3u8', 'pls', 'cue', 'bash', 'vue', 'eml', 'msg', 'csv', 'bat', 'twig', 'tpl', 'md', 'gitignore', 'less', 'sass', 'scss', 'c', 'cpp', 'cs', 'py', 'go', 'zsh', 'swift', 'map', 'lock', 'dtd', 'svg', 'asp', 'aspx', 'asx', 'asmx', 'ashx', 'jsp', 'jspx', 'cgi', 'dockerfile', 'ruby', 'yml', 'yaml', 'toml', 'vhost', 'scpt', 'applescript', 'csx', 'cshtml', 'c++', 'coffee', 'cfm', 'rb', 'graphql', 'mustache', 'jinja', 'http', 'handlebars', 'java', 'es', 'es6', 'markdown', 'wiki', 'tmp', 'top', 'bot', 'dat', 'bak', 'htpasswd', 'pl' ); } /** * Get mime types of text files * @return array */ function fm_get_text_mimes() { return array( 'application/xml', 'application/javascript', 'application/x-javascript', 'image/svg+xml', 'message/rfc822', 'application/json', ); } /** * Get file names of text files w/o extensions * @return array */ function fm_get_text_names() { return array( 'license', 'readme', 'authors', 'contributors', 'changelog', ); } /** * Get online docs viewer supported files extensions * @return array */ function fm_get_onlineViewer_exts() { return array('doc', 'docx', 'xls', 'xlsx', 'pdf', 'ppt', 'pptx', 'ai', 'psd', 'dxf', 'xps', 'rar', 'odt', 'ods'); } /** * It returns the mime type of a file based on its extension. * @param extension The file extension of the file you want to get the mime type for. * @return string|string[] The mime type of the file. */ function fm_get_file_mimes($extension) { $fileTypes['swf'] = 'application/x-shockwave-flash'; $fileTypes['pdf'] = 'application/pdf'; $fileTypes['exe'] = 'application/octet-stream'; $fileTypes['zip'] = 'application/zip'; $fileTypes['doc'] = 'application/msword'; $fileTypes['xls'] = 'application/vnd.ms-excel'; $fileTypes['ppt'] = 'application/vnd.ms-powerpoint'; $fileTypes['gif'] = 'image/gif'; $fileTypes['png'] = 'image/png'; $fileTypes['jpeg'] = 'image/jpg'; $fileTypes['jpg'] = 'image/jpg'; $fileTypes['webp'] = 'image/webp'; $fileTypes['avif'] = 'image/avif'; $fileTypes['rar'] = 'application/rar'; $fileTypes['ra'] = 'audio/x-pn-realaudio'; $fileTypes['ram'] = 'audio/x-pn-realaudio'; $fileTypes['ogg'] = 'audio/x-pn-realaudio'; $fileTypes['wav'] = 'video/x-msvideo'; $fileTypes['wmv'] = 'video/x-msvideo'; $fileTypes['avi'] = 'video/x-msvideo'; $fileTypes['asf'] = 'video/x-msvideo'; $fileTypes['divx'] = 'video/x-msvideo'; $fileTypes['mp3'] = 'audio/mpeg'; $fileTypes['mp4'] = 'audio/mpeg'; $fileTypes['mpeg'] = 'video/mpeg'; $fileTypes['mpg'] = 'video/mpeg'; $fileTypes['mpe'] = 'video/mpeg'; $fileTypes['mov'] = 'video/quicktime'; $fileTypes['swf'] = 'video/quicktime'; $fileTypes['3gp'] = 'video/quicktime'; $fileTypes['m4a'] = 'video/quicktime'; $fileTypes['aac'] = 'video/quicktime'; $fileTypes['m3u'] = 'video/quicktime'; $fileTypes['php'] = ['application/x-php']; $fileTypes['html'] = ['text/html']; $fileTypes['txt'] = ['text/plain']; //Unknown mime-types should be 'application/octet-stream' if(empty($fileTypes[$extension])) { $fileTypes[$extension] = ['application/octet-stream']; } return $fileTypes[$extension]; } /** * This function scans the files and folder recursively, and return matching files * @param string $dir * @param string $filter * @return array|null */ function scan($dir = '', $filter = '') { $path = FM_ROOT_PATH.'/'.$dir; if($path) { $ite = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)); $rii = new RegexIterator($ite, "/(" . $filter . ")/i"); $files = array(); foreach ($rii as $file) { if (!$file->isDir()) { $fileName = $file->getFilename(); $location = str_replace(FM_ROOT_PATH, '', $file->getPath()); $files[] = array( "name" => $fileName, "type" => "file", "path" => $location, ); } } return $files; } } /** * Parameters: downloadFile(File Location, File Name, * max speed, is streaming * If streaming - videos will show as videos, images as images * instead of download prompt * https://stackoverflow.com/a/13821992/1164642 */ function fm_download_file($fileLocation, $fileName, $chunkSize = 1024) { if (connection_status() != 0) return (false); $extension = pathinfo($fileName, PATHINFO_EXTENSION); $contentType = fm_get_file_mimes($extension); if(is_array($contentType)) { $contentType = implode(' ', $contentType); } $size = filesize($fileLocation); if ($size == 0) { fm_set_msg(lng('Zero byte file! Aborting download'), 'error'); $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH)); return (false); } @ini_set('magic_quotes_runtime', 0); $fp = fopen("$fileLocation", "rb"); if ($fp === false) { fm_set_msg(lng('Cannot open file! Aborting download'), 'error'); $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH)); return (false); } // headers header('Content-Description: File Transfer'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); header("Content-Transfer-Encoding: binary"); header("Content-Type: $contentType"); $contentDisposition = 'attachment'; if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) { $fileName = preg_replace('/\./', '%2e', $fileName, substr_count($fileName, '.') - 1); header("Content-Disposition: $contentDisposition;filename=\"$fileName\""); } else { header("Content-Disposition: $contentDisposition;filename=\"$fileName\""); } header("Accept-Ranges: bytes"); $range = 0; if (isset($_SERVER['HTTP_RANGE'])) { list($a, $range) = explode("=", $_SERVER['HTTP_RANGE']); str_replace($range, "-", $range); $size2 = $size - 1; $new_length = $size - $range; header("HTTP/1.1 206 Partial Content"); header("Content-Length: $new_length"); header("Content-Range: bytes $range$size2/$size"); } else { $size2 = $size - 1; header("Content-Range: bytes 0-$size2/$size"); header("Content-Length: " . $size); } $fileLocation = realpath($fileLocation); while (ob_get_level()) ob_end_clean(); readfile($fileLocation); fclose($fp); return ((connection_status() == 0) and !connection_aborted()); } /** * If the theme is dark, return the text-white and bg-dark classes. * @return string the value of the variable. */ function fm_get_theme() { $result = ''; if(FM_THEME == "dark") { $result = "text-white bg-dark"; } return $result; } /** * Class to work with zip files (using ZipArchive) */ class FM_Zipper { private $zip; public function __construct() { $this->zip = new ZipArchive(); } /** * Create archive with name $filename and files $files (RELATIVE PATHS!) * @param string $filename * @param array|string $files * @return bool */ public function create($filename, $files) { $res = $this->zip->open($filename, ZipArchive::CREATE); if ($res !== true) { return false; } if (is_array($files)) { foreach ($files as $f) { $f = fm_clean_path($f); if (!$this->addFileOrDir($f)) { $this->zip->close(); return false; } } $this->zip->close(); return true; } else { if ($this->addFileOrDir($files)) { $this->zip->close(); return true; } return false; } } /** * Extract archive $filename to folder $path (RELATIVE OR ABSOLUTE PATHS) * @param string $filename * @param string $path * @return bool */ public function unzip($filename, $path) { $res = $this->zip->open($filename); if ($res !== true) { return false; } if ($this->zip->extractTo($path)) { $this->zip->close(); return true; } return false; } /** * Add file/folder to archive * @param string $filename * @return bool */ private function addFileOrDir($filename) { if (is_file($filename)) { return $this->zip->addFile($filename); } elseif (is_dir($filename)) { return $this->addDir($filename); } return false; } /** * Add folder recursively * @param string $path * @return bool */ private function addDir($path) { if (!$this->zip->addEmptyDir($path)) { return false; } $objects = scandir($path); if (is_array($objects)) { foreach ($objects as $file) { if ($file != '.' && $file != '..') { if (is_dir($path . '/' . $file)) { if (!$this->addDir($path . '/' . $file)) { return false; } } elseif (is_file($path . '/' . $file)) { if (!$this->zip->addFile($path . '/' . $file)) { return false; } } } } return true; } return false; } } /** * Class to work with Tar files (using PharData) */ class FM_Zipper_Tar { private $tar; public function __construct() { $this->tar = null; } /** * Create archive with name $filename and files $files (RELATIVE PATHS!) * @param string $filename * @param array|string $files * @return bool */ public function create($filename, $files) { $this->tar = new PharData($filename); if (is_array($files)) { foreach ($files as $f) { $f = fm_clean_path($f); if (!$this->addFileOrDir($f)) { return false; } } return true; } else { if ($this->addFileOrDir($files)) { return true; } return false; } } /** * Extract archive $filename to folder $path (RELATIVE OR ABSOLUTE PATHS) * @param string $filename * @param string $path * @return bool */ public function unzip($filename, $path) { $res = $this->tar->open($filename); if ($res !== true) { return false; } if ($this->tar->extractTo($path)) { return true; } return false; } /** * Add file/folder to archive * @param string $filename * @return bool */ private function addFileOrDir($filename) { if (is_file($filename)) { try { $this->tar->addFile($filename); return true; } catch (Exception $e) { return false; } } elseif (is_dir($filename)) { return $this->addDir($filename); } return false; } /** * Add folder recursively * @param string $path * @return bool */ private function addDir($path) { $objects = scandir($path); if (is_array($objects)) { foreach ($objects as $file) { if ($file != '.' && $file != '..') { if (is_dir($path . '/' . $file)) { if (!$this->addDir($path . '/' . $file)) { return false; } } elseif (is_file($path . '/' . $file)) { try { $this->tar->addFile($path . '/' . $file); } catch (Exception $e) { return false; } } } } return true; } return false; } } /** * Save Configuration */ class FM_Config { var $data; function __construct() { global $root_path, $root_url, $CONFIG; $fm_url = $root_url.$_SERVER["PHP_SELF"]; $this->data = array( 'lang' => 'en', 'error_reporting' => true, 'show_hidden' => true ); $data = false; if (strlen($CONFIG)) { $data = fm_object_to_array(json_decode($CONFIG)); } else { $msg = 'Tiny File Manager
Error: Cannot load configuration'; if (substr($fm_url, -1) == '/') { $fm_url = rtrim($fm_url, '/'); $msg .= '
'; $msg .= '
Seems like you have a trailing slash on the URL.'; $msg .= '
Try this link: ' . $fm_url . ''; } die($msg); } if (is_array($data) && count($data)) $this->data = $data; else $this->save(); } function save() { $fm_file = __FILE__; $var_name = '$CONFIG'; $var_value = var_export(json_encode($this->data), true); $config_string = " ' . $_SESSION[FM_SESSION_ID]['message'] . '

'; unset($_SESSION[FM_SESSION_ID]['message']); unset($_SESSION[FM_SESSION_ID]['status']); } } /** * Show page header in Login Form */ function fm_show_header_login() { $sprites_ver = '20160315'; header("Content-Type: text/html; charset=utf-8"); header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0"); header("Pragma: no-cache"); global $lang, $root_url, $favicon_path; ?> '; } ?> <?php echo fm_enc(APP_TITLE) ?> ">
'; } ?> <?php echo fm_enc(APP_TITLE) ?> ">
src/Utility/InputValidator.php000064400000004720150211046430012453 0ustar00headers = new Headers(); $this->cookies = new Jar(); } /** * Is the response a redirect? * * @return boolean True if redirect (3xx status), false if not. */ public function is_redirect() { $code = $this->status_code; return in_array($code, [300, 301, 302, 303, 307], true) || $code > 307 && $code < 400; } /** * Throws an exception if the request was not successful * * @param boolean $allow_redirects Set to false to throw on a 3xx as well * * @throws \WpOrg\Requests\Exception If `$allow_redirects` is false, and code is 3xx (`response.no_redirects`) * @throws \WpOrg\Requests\Exception\Http On non-successful status code. Exception class corresponds to "Status" + code (e.g. {@see \WpOrg\Requests\Exception\Http\Status404}) */ public function throw_for_status($allow_redirects = true) { if ($this->is_redirect()) { if ($allow_redirects !== true) { throw new Exception('Redirection not allowed', 'response.no_redirects', $this); } } elseif (!$this->success) { $exception = Http::get_class($this->status_code); throw new $exception(null, $this); } } /** * JSON decode the response body. * * The method parameters are the same as those for the PHP native `json_decode()` function. * * @link https://php.net/json-decode * * @param bool|null $associative Optional. When `true`, JSON objects will be returned as associative arrays; * When `false`, JSON objects will be returned as objects. * When `null`, JSON objects will be returned as associative arrays * or objects depending on whether `JSON_OBJECT_AS_ARRAY` is set in the flags. * Defaults to `true` (in contrast to the PHP native default of `null`). * @param int $depth Optional. Maximum nesting depth of the structure being decoded. * Defaults to `512`. * @param int $options Optional. Bitmask of JSON_BIGINT_AS_STRING, JSON_INVALID_UTF8_IGNORE, * JSON_INVALID_UTF8_SUBSTITUTE, JSON_OBJECT_AS_ARRAY, JSON_THROW_ON_ERROR. * Defaults to `0` (no options set). * * @return array * * @throws \WpOrg\Requests\Exception If `$this->body` is not valid json. */ public function decode_body($associative = true, $depth = 512, $options = 0) { $data = json_decode($this->body, $associative, $depth, $options); if (json_last_error() !== JSON_ERROR_NONE) { $last_error = json_last_error_msg(); throw new Exception('Unable to parse JSON data: ' . $last_error, 'response.invalid', $this); } return $data; } } src/Transport.php000064400000003010150211046430010026 0ustar00 $capabilities Optional. Associative array of capabilities to test against, i.e. `['' => true]`. * @return bool Whether the transport can be used. */ public static function test($capabilities = []); } src/Auth/Basic.php000064400000004755150211046430007775 0ustar00user, $this->pass) = $args; return; } if ($args !== null) { throw InvalidArgument::create(1, '$args', 'array|null', gettype($args)); } } /** * Register the necessary callbacks * * @see \WpOrg\Requests\Auth\Basic::curl_before_send() * @see \WpOrg\Requests\Auth\Basic::fsockopen_header() * @param \WpOrg\Requests\Hooks $hooks Hook system */ public function register(Hooks $hooks) { $hooks->register('curl.before_send', [$this, 'curl_before_send']); $hooks->register('fsockopen.after_headers', [$this, 'fsockopen_header']); } /** * Set cURL parameters before the data is sent * * @param resource|\CurlHandle $handle cURL handle */ public function curl_before_send(&$handle) { curl_setopt($handle, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); curl_setopt($handle, CURLOPT_USERPWD, $this->getAuthString()); } /** * Add extra headers to the request before sending * * @param string $out HTTP header string */ public function fsockopen_header(&$out) { $out .= sprintf("Authorization: Basic %s\r\n", base64_encode($this->getAuthString())); } /** * Get the authentication string (user:pass) * * @return string */ public function getAuthString() { return $this->user . ':' . $this->pass; } } src/Requests.php000064400000102321150211046430007652 0ustar00 10, 'connect_timeout' => 10, 'useragent' => 'php-requests/' . self::VERSION, 'protocol_version' => 1.1, 'redirected' => 0, 'redirects' => 10, 'follow_redirects' => true, 'blocking' => true, 'type' => self::GET, 'filename' => false, 'auth' => false, 'proxy' => false, 'cookies' => false, 'max_bytes' => false, 'idn' => true, 'hooks' => null, 'transport' => null, 'verify' => null, 'verifyname' => true, ]; /** * Default supported Transport classes. * * @since 2.0.0 * * @var array */ const DEFAULT_TRANSPORTS = [ Curl::class => Curl::class, Fsockopen::class => Fsockopen::class, ]; /** * Current version of Requests * * @var string */ const VERSION = '2.0.11'; /** * Selected transport name * * Use {@see \WpOrg\Requests\Requests::get_transport()} instead * * @var array */ public static $transport = []; /** * Registered transport classes * * @var array */ protected static $transports = []; /** * Default certificate path. * * @see \WpOrg\Requests\Requests::get_certificate_path() * @see \WpOrg\Requests\Requests::set_certificate_path() * * @var string */ protected static $certificate_path = __DIR__ . '/../certificates/cacert.pem'; /** * All (known) valid deflate, gzip header magic markers. * * These markers relate to different compression levels. * * @link https://stackoverflow.com/a/43170354/482864 Marker source. * * @since 2.0.0 * * @var array */ private static $magic_compression_headers = [ "\x1f\x8b" => true, // Gzip marker. "\x78\x01" => true, // Zlib marker - level 1. "\x78\x5e" => true, // Zlib marker - level 2 to 5. "\x78\x9c" => true, // Zlib marker - level 6. "\x78\xda" => true, // Zlib marker - level 7 to 9. ]; /** * This is a static class, do not instantiate it * * @codeCoverageIgnore */ private function __construct() {} /** * Register a transport * * @param string $transport Transport class to add, must support the \WpOrg\Requests\Transport interface */ public static function add_transport($transport) { if (empty(self::$transports)) { self::$transports = self::DEFAULT_TRANSPORTS; } self::$transports[$transport] = $transport; } /** * Get the fully qualified class name (FQCN) for a working transport. * * @param array $capabilities Optional. Associative array of capabilities to test against, i.e. `['' => true]`. * @return string FQCN of the transport to use, or an empty string if no transport was * found which provided the requested capabilities. */ protected static function get_transport_class(array $capabilities = []) { // Caching code, don't bother testing coverage. // @codeCoverageIgnoreStart // Array of capabilities as a string to be used as an array key. ksort($capabilities); $cap_string = serialize($capabilities); // Don't search for a transport if it's already been done for these $capabilities. if (isset(self::$transport[$cap_string])) { return self::$transport[$cap_string]; } // Ensure we will not run this same check again later on. self::$transport[$cap_string] = ''; // @codeCoverageIgnoreEnd if (empty(self::$transports)) { self::$transports = self::DEFAULT_TRANSPORTS; } // Find us a working transport. foreach (self::$transports as $class) { if (!class_exists($class)) { continue; } $result = $class::test($capabilities); if ($result === true) { self::$transport[$cap_string] = $class; break; } } return self::$transport[$cap_string]; } /** * Get a working transport. * * @param array $capabilities Optional. Associative array of capabilities to test against, i.e. `['' => true]`. * @return \WpOrg\Requests\Transport * @throws \WpOrg\Requests\Exception If no valid transport is found (`notransport`). */ protected static function get_transport(array $capabilities = []) { $class = self::get_transport_class($capabilities); if ($class === '') { throw new Exception('No working transports found', 'notransport', self::$transports); } return new $class(); } /** * Checks to see if we have a transport for the capabilities requested. * * Supported capabilities can be found in the {@see \WpOrg\Requests\Capability} * interface as constants. * * Example usage: * `Requests::has_capabilities([Capability::SSL => true])`. * * @param array $capabilities Optional. Associative array of capabilities to test against, i.e. `['' => true]`. * @return bool Whether the transport has the requested capabilities. */ public static function has_capabilities(array $capabilities = []) { return self::get_transport_class($capabilities) !== ''; } /**#@+ * @see \WpOrg\Requests\Requests::request() * @param string $url * @param array $headers * @param array $options * @return \WpOrg\Requests\Response */ /** * Send a GET request */ public static function get($url, $headers = [], $options = []) { return self::request($url, $headers, null, self::GET, $options); } /** * Send a HEAD request */ public static function head($url, $headers = [], $options = []) { return self::request($url, $headers, null, self::HEAD, $options); } /** * Send a DELETE request */ public static function delete($url, $headers = [], $options = []) { return self::request($url, $headers, null, self::DELETE, $options); } /** * Send a TRACE request */ public static function trace($url, $headers = [], $options = []) { return self::request($url, $headers, null, self::TRACE, $options); } /**#@-*/ /**#@+ * @see \WpOrg\Requests\Requests::request() * @param string $url * @param array $headers * @param array $data * @param array $options * @return \WpOrg\Requests\Response */ /** * Send a POST request */ public static function post($url, $headers = [], $data = [], $options = []) { return self::request($url, $headers, $data, self::POST, $options); } /** * Send a PUT request */ public static function put($url, $headers = [], $data = [], $options = []) { return self::request($url, $headers, $data, self::PUT, $options); } /** * Send an OPTIONS request */ public static function options($url, $headers = [], $data = [], $options = []) { return self::request($url, $headers, $data, self::OPTIONS, $options); } /** * Send a PATCH request * * Note: Unlike {@see \WpOrg\Requests\Requests::post()} and {@see \WpOrg\Requests\Requests::put()}, * `$headers` is required, as the specification recommends that should send an ETag * * @link https://tools.ietf.org/html/rfc5789 */ public static function patch($url, $headers, $data = [], $options = []) { return self::request($url, $headers, $data, self::PATCH, $options); } /**#@-*/ /** * Main interface for HTTP requests * * This method initiates a request and sends it via a transport before * parsing. * * The `$options` parameter takes an associative array with the following * options: * * - `timeout`: How long should we wait for a response? * Note: for cURL, a minimum of 1 second applies, as DNS resolution * operates at second-resolution only. * (float, seconds with a millisecond precision, default: 10, example: 0.01) * - `connect_timeout`: How long should we wait while trying to connect? * (float, seconds with a millisecond precision, default: 10, example: 0.01) * - `useragent`: Useragent to send to the server * (string, default: php-requests/$version) * - `follow_redirects`: Should we follow 3xx redirects? * (boolean, default: true) * - `redirects`: How many times should we redirect before erroring? * (integer, default: 10) * - `blocking`: Should we block processing on this request? * (boolean, default: true) * - `filename`: File to stream the body to instead. * (string|boolean, default: false) * - `auth`: Authentication handler or array of user/password details to use * for Basic authentication * (\WpOrg\Requests\Auth|array|boolean, default: false) * - `proxy`: Proxy details to use for proxy by-passing and authentication * (\WpOrg\Requests\Proxy|array|string|boolean, default: false) * - `max_bytes`: Limit for the response body size. * (integer|boolean, default: false) * - `idn`: Enable IDN parsing * (boolean, default: true) * - `transport`: Custom transport. Either a class name, or a * transport object. Defaults to the first working transport from * {@see \WpOrg\Requests\Requests::getTransport()} * (string|\WpOrg\Requests\Transport, default: {@see \WpOrg\Requests\Requests::getTransport()}) * - `hooks`: Hooks handler. * (\WpOrg\Requests\HookManager, default: new WpOrg\Requests\Hooks()) * - `verify`: Should we verify SSL certificates? Allows passing in a custom * certificate file as a string. (Using true uses the system-wide root * certificate store instead, but this may have different behaviour * across transports.) * (string|boolean, default: certificates/cacert.pem) * - `verifyname`: Should we verify the common name in the SSL certificate? * (boolean, default: true) * - `data_format`: How should we send the `$data` parameter? * (string, one of 'query' or 'body', default: 'query' for * HEAD/GET/DELETE, 'body' for POST/PUT/OPTIONS/PATCH) * * @param string|Stringable $url URL to request * @param array $headers Extra headers to send with the request * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests * @param string $type HTTP request type (use Requests constants) * @param array $options Options for the request (see description for more information) * @return \WpOrg\Requests\Response * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $url argument is not a string or Stringable. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $type argument is not a string. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. * @throws \WpOrg\Requests\Exception On invalid URLs (`nonhttp`) */ public static function request($url, $headers = [], $data = [], $type = self::GET, $options = []) { if (InputValidator::is_string_or_stringable($url) === false) { throw InvalidArgument::create(1, '$url', 'string|Stringable', gettype($url)); } if (is_string($type) === false) { throw InvalidArgument::create(4, '$type', 'string', gettype($type)); } if (is_array($options) === false) { throw InvalidArgument::create(5, '$options', 'array', gettype($options)); } if (empty($options['type'])) { $options['type'] = $type; } $options = array_merge(self::get_default_options(), $options); self::set_defaults($url, $headers, $data, $type, $options); $options['hooks']->dispatch('requests.before_request', [&$url, &$headers, &$data, &$type, &$options]); if (!empty($options['transport'])) { $transport = $options['transport']; if (is_string($options['transport'])) { $transport = new $transport(); } } else { $need_ssl = (stripos($url, 'https://') === 0); $capabilities = [Capability::SSL => $need_ssl]; $transport = self::get_transport($capabilities); } $response = $transport->request($url, $headers, $data, $options); $options['hooks']->dispatch('requests.before_parse', [&$response, $url, $headers, $data, $type, $options]); return self::parse_response($response, $url, $headers, $data, $options); } /** * Send multiple HTTP requests simultaneously * * The `$requests` parameter takes an associative or indexed array of * request fields. The key of each request can be used to match up the * request with the returned data, or with the request passed into your * `multiple.request.complete` callback. * * The request fields value is an associative array with the following keys: * * - `url`: Request URL Same as the `$url` parameter to * {@see \WpOrg\Requests\Requests::request()} * (string, required) * - `headers`: Associative array of header fields. Same as the `$headers` * parameter to {@see \WpOrg\Requests\Requests::request()} * (array, default: `array()`) * - `data`: Associative array of data fields or a string. Same as the * `$data` parameter to {@see \WpOrg\Requests\Requests::request()} * (array|string, default: `array()`) * - `type`: HTTP request type (use \WpOrg\Requests\Requests constants). Same as the `$type` * parameter to {@see \WpOrg\Requests\Requests::request()} * (string, default: `\WpOrg\Requests\Requests::GET`) * - `cookies`: Associative array of cookie name to value, or cookie jar. * (array|\WpOrg\Requests\Cookie\Jar) * * If the `$options` parameter is specified, individual requests will * inherit options from it. This can be used to use a single hooking system, * or set all the types to `\WpOrg\Requests\Requests::POST`, for example. * * In addition, the `$options` parameter takes the following global options: * * - `complete`: A callback for when a request is complete. Takes two * parameters, a \WpOrg\Requests\Response/\WpOrg\Requests\Exception reference, and the * ID from the request array (Note: this can also be overridden on a * per-request basis, although that's a little silly) * (callback) * * @param array $requests Requests data (see description for more information) * @param array $options Global and default options (see {@see \WpOrg\Requests\Requests::request()}) * @return array Responses (either \WpOrg\Requests\Response or a \WpOrg\Requests\Exception object) * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $requests argument is not an array or iterable object with array access. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. */ public static function request_multiple($requests, $options = []) { if (InputValidator::has_array_access($requests) === false || InputValidator::is_iterable($requests) === false) { throw InvalidArgument::create(1, '$requests', 'array|ArrayAccess&Traversable', gettype($requests)); } if (is_array($options) === false) { throw InvalidArgument::create(2, '$options', 'array', gettype($options)); } $options = array_merge(self::get_default_options(true), $options); if (!empty($options['hooks'])) { $options['hooks']->register('transport.internal.parse_response', [static::class, 'parse_multiple']); if (!empty($options['complete'])) { $options['hooks']->register('multiple.request.complete', $options['complete']); } } foreach ($requests as $id => &$request) { if (!isset($request['headers'])) { $request['headers'] = []; } if (!isset($request['data'])) { $request['data'] = []; } if (!isset($request['type'])) { $request['type'] = self::GET; } if (!isset($request['options'])) { $request['options'] = $options; $request['options']['type'] = $request['type']; } else { if (empty($request['options']['type'])) { $request['options']['type'] = $request['type']; } $request['options'] = array_merge($options, $request['options']); } self::set_defaults($request['url'], $request['headers'], $request['data'], $request['type'], $request['options']); // Ensure we only hook in once if ($request['options']['hooks'] !== $options['hooks']) { $request['options']['hooks']->register('transport.internal.parse_response', [static::class, 'parse_multiple']); if (!empty($request['options']['complete'])) { $request['options']['hooks']->register('multiple.request.complete', $request['options']['complete']); } } } unset($request); if (!empty($options['transport'])) { $transport = $options['transport']; if (is_string($options['transport'])) { $transport = new $transport(); } } else { $transport = self::get_transport(); } $responses = $transport->request_multiple($requests, $options); foreach ($responses as $id => &$response) { // If our hook got messed with somehow, ensure we end up with the // correct response if (is_string($response)) { $request = $requests[$id]; self::parse_multiple($response, $request); $request['options']['hooks']->dispatch('multiple.request.complete', [&$response, $id]); } } return $responses; } /** * Get the default options * * @see \WpOrg\Requests\Requests::request() for values returned by this method * @param boolean $multirequest Is this a multirequest? * @return array Default option values */ protected static function get_default_options($multirequest = false) { $defaults = static::OPTION_DEFAULTS; $defaults['verify'] = self::$certificate_path; if ($multirequest !== false) { $defaults['complete'] = null; } return $defaults; } /** * Get default certificate path. * * @return string Default certificate path. */ public static function get_certificate_path() { return self::$certificate_path; } /** * Set default certificate path. * * @param string|Stringable|bool $path Certificate path, pointing to a PEM file. * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $url argument is not a string, Stringable or boolean. */ public static function set_certificate_path($path) { if (InputValidator::is_string_or_stringable($path) === false && is_bool($path) === false) { throw InvalidArgument::create(1, '$path', 'string|Stringable|bool', gettype($path)); } self::$certificate_path = $path; } /** * Set the default values * * The $options parameter is updated with the results. * * @param string $url URL to request * @param array $headers Extra headers to send with the request * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests * @param string $type HTTP request type * @param array $options Options for the request * @return void * * @throws \WpOrg\Requests\Exception When the $url is not an http(s) URL. */ protected static function set_defaults(&$url, &$headers, &$data, &$type, &$options) { if (!preg_match('/^http(s)?:\/\//i', $url, $matches)) { throw new Exception('Only HTTP(S) requests are handled.', 'nonhttp', $url); } if (empty($options['hooks'])) { $options['hooks'] = new Hooks(); } if (is_array($options['auth'])) { $options['auth'] = new Basic($options['auth']); } if ($options['auth'] !== false) { $options['auth']->register($options['hooks']); } if (is_string($options['proxy']) || is_array($options['proxy'])) { $options['proxy'] = new Http($options['proxy']); } if ($options['proxy'] !== false) { $options['proxy']->register($options['hooks']); } if (is_array($options['cookies'])) { $options['cookies'] = new Jar($options['cookies']); } elseif (empty($options['cookies'])) { $options['cookies'] = new Jar(); } if ($options['cookies'] !== false) { $options['cookies']->register($options['hooks']); } if ($options['idn'] !== false) { $iri = new Iri($url); $iri->host = IdnaEncoder::encode($iri->ihost); $url = $iri->uri; } // Massage the type to ensure we support it. $type = strtoupper($type); if (!isset($options['data_format'])) { if (in_array($type, [self::HEAD, self::GET, self::DELETE], true)) { $options['data_format'] = 'query'; } else { $options['data_format'] = 'body'; } } } /** * HTTP response parser * * @param string $headers Full response text including headers and body * @param string $url Original request URL * @param array $req_headers Original $headers array passed to {@link request()}, in case we need to follow redirects * @param array $req_data Original $data array passed to {@link request()}, in case we need to follow redirects * @param array $options Original $options array passed to {@link request()}, in case we need to follow redirects * @return \WpOrg\Requests\Response * * @throws \WpOrg\Requests\Exception On missing head/body separator (`requests.no_crlf_separator`) * @throws \WpOrg\Requests\Exception On missing head/body separator (`noversion`) * @throws \WpOrg\Requests\Exception On missing head/body separator (`toomanyredirects`) */ protected static function parse_response($headers, $url, $req_headers, $req_data, $options) { $return = new Response(); if (!$options['blocking']) { return $return; } $return->raw = $headers; $return->url = (string) $url; $return->body = ''; if (!$options['filename']) { $pos = strpos($headers, "\r\n\r\n"); if ($pos === false) { // Crap! throw new Exception('Missing header/body separator', 'requests.no_crlf_separator'); } $headers = substr($return->raw, 0, $pos); // Headers will always be separated from the body by two new lines - `\n\r\n\r`. $body = substr($return->raw, $pos + 4); if (!empty($body)) { $return->body = $body; } } // Pretend CRLF = LF for compatibility (RFC 2616, section 19.3) $headers = str_replace("\r\n", "\n", $headers); // Unfold headers (replace [CRLF] 1*( SP | HT ) with SP) as per RFC 2616 (section 2.2) $headers = preg_replace('/\n[ \t]/', ' ', $headers); $headers = explode("\n", $headers); preg_match('#^HTTP/(1\.\d)[ \t]+(\d+)#i', array_shift($headers), $matches); if (empty($matches)) { throw new Exception('Response could not be parsed', 'noversion', $headers); } $return->protocol_version = (float) $matches[1]; $return->status_code = (int) $matches[2]; if ($return->status_code >= 200 && $return->status_code < 300) { $return->success = true; } foreach ($headers as $header) { list($key, $value) = explode(':', $header, 2); $value = trim($value); preg_replace('#(\s+)#i', ' ', $value); $return->headers[$key] = $value; } if (isset($return->headers['transfer-encoding'])) { $return->body = self::decode_chunked($return->body); unset($return->headers['transfer-encoding']); } if (isset($return->headers['content-encoding'])) { $return->body = self::decompress($return->body); } //fsockopen and cURL compatibility if (isset($return->headers['connection'])) { unset($return->headers['connection']); } $options['hooks']->dispatch('requests.before_redirect_check', [&$return, $req_headers, $req_data, $options]); if ($return->is_redirect() && $options['follow_redirects'] === true) { if (isset($return->headers['location']) && $options['redirected'] < $options['redirects']) { if ($return->status_code === 303) { $options['type'] = self::GET; } $options['redirected']++; $location = $return->headers['location']; if (strpos($location, 'http://') !== 0 && strpos($location, 'https://') !== 0) { // relative redirect, for compatibility make it absolute $location = Iri::absolutize($url, $location); $location = $location->uri; } $hook_args = [ &$location, &$req_headers, &$req_data, &$options, $return, ]; $options['hooks']->dispatch('requests.before_redirect', $hook_args); $redirected = self::request($location, $req_headers, $req_data, $options['type'], $options); $redirected->history[] = $return; return $redirected; } elseif ($options['redirected'] >= $options['redirects']) { throw new Exception('Too many redirects', 'toomanyredirects', $return); } } $return->redirects = $options['redirected']; $options['hooks']->dispatch('requests.after_request', [&$return, $req_headers, $req_data, $options]); return $return; } /** * Callback for `transport.internal.parse_response` * * Internal use only. Converts a raw HTTP response to a \WpOrg\Requests\Response * while still executing a multiple request. * * `$response` is either set to a \WpOrg\Requests\Response instance, or a \WpOrg\Requests\Exception object * * @param string $response Full response text including headers and body (will be overwritten with Response instance) * @param array $request Request data as passed into {@see \WpOrg\Requests\Requests::request_multiple()} * @return void */ public static function parse_multiple(&$response, $request) { try { $url = $request['url']; $headers = $request['headers']; $data = $request['data']; $options = $request['options']; $response = self::parse_response($response, $url, $headers, $data, $options); } catch (Exception $e) { $response = $e; } } /** * Decoded a chunked body as per RFC 2616 * * @link https://tools.ietf.org/html/rfc2616#section-3.6.1 * @param string $data Chunked body * @return string Decoded body */ protected static function decode_chunked($data) { if (!preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', trim($data))) { return $data; } $decoded = ''; $encoded = $data; while (true) { $is_chunked = (bool) preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', $encoded, $matches); if (!$is_chunked) { // Looks like it's not chunked after all return $data; } $length = hexdec(trim($matches[1])); if ($length === 0) { // Ignore trailer headers return $decoded; } $chunk_length = strlen($matches[0]); $decoded .= substr($encoded, $chunk_length, $length); $encoded = substr($encoded, $chunk_length + $length + 2); if (trim($encoded) === '0' || empty($encoded)) { return $decoded; } } // We'll never actually get down here // @codeCoverageIgnoreStart } // @codeCoverageIgnoreEnd /** * Convert a key => value array to a 'key: value' array for headers * * @param iterable $dictionary Dictionary of header values * @return array List of headers * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not iterable. */ public static function flatten($dictionary) { if (InputValidator::is_iterable($dictionary) === false) { throw InvalidArgument::create(1, '$dictionary', 'iterable', gettype($dictionary)); } $return = []; foreach ($dictionary as $key => $value) { $return[] = sprintf('%s: %s', $key, $value); } return $return; } /** * Decompress an encoded body * * Implements gzip, compress and deflate. Guesses which it is by attempting * to decode. * * @param string $data Compressed data in one of the above formats * @return string Decompressed string * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string. */ public static function decompress($data) { if (is_string($data) === false) { throw InvalidArgument::create(1, '$data', 'string', gettype($data)); } if (trim($data) === '') { // Empty body does not need further processing. return $data; } $marker = substr($data, 0, 2); if (!isset(self::$magic_compression_headers[$marker])) { // Not actually compressed. Probably cURL ruining this for us. return $data; } if (function_exists('gzdecode')) { $decoded = @gzdecode($data); if ($decoded !== false) { return $decoded; } } if (function_exists('gzinflate')) { $decoded = @gzinflate($data); if ($decoded !== false) { return $decoded; } } $decoded = self::compatible_gzinflate($data); if ($decoded !== false) { return $decoded; } if (function_exists('gzuncompress')) { $decoded = @gzuncompress($data); if ($decoded !== false) { return $decoded; } } return $data; } /** * Decompression of deflated string while staying compatible with the majority of servers. * * Certain Servers will return deflated data with headers which PHP's gzinflate() * function cannot handle out of the box. The following function has been created from * various snippets on the gzinflate() PHP documentation. * * Warning: Magic numbers within. Due to the potential different formats that the compressed * data may be returned in, some "magic offsets" are needed to ensure proper decompression * takes place. For a simple progmatic way to determine the magic offset in use, see: * https://core.trac.wordpress.org/ticket/18273 * * @since 1.6.0 * @link https://core.trac.wordpress.org/ticket/18273 * @link https://www.php.net/gzinflate#70875 * @link https://www.php.net/gzinflate#77336 * * @param string $gz_data String to decompress. * @return string|bool False on failure. * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string. */ public static function compatible_gzinflate($gz_data) { if (is_string($gz_data) === false) { throw InvalidArgument::create(1, '$gz_data', 'string', gettype($gz_data)); } if (trim($gz_data) === '') { return false; } // Compressed data might contain a full zlib header, if so strip it for // gzinflate() if (substr($gz_data, 0, 3) === "\x1f\x8b\x08") { $i = 10; $flg = ord(substr($gz_data, 3, 1)); if ($flg > 0) { if ($flg & 4) { list($xlen) = unpack('v', substr($gz_data, $i, 2)); $i += 2 + $xlen; } if ($flg & 8) { $i = strpos($gz_data, "\0", $i) + 1; } if ($flg & 16) { $i = strpos($gz_data, "\0", $i) + 1; } if ($flg & 2) { $i += 2; } } $decompressed = self::compatible_gzinflate(substr($gz_data, $i)); if ($decompressed !== false) { return $decompressed; } } // If the data is Huffman Encoded, we must first strip the leading 2 // byte Huffman marker for gzinflate() // The response is Huffman coded by many compressors such as // java.util.zip.Deflater, Ruby's Zlib::Deflate, and .NET's // System.IO.Compression.DeflateStream. // // See https://decompres.blogspot.com/ for a quick explanation of this // data type $huffman_encoded = false; // low nibble of first byte should be 0x08 list(, $first_nibble) = unpack('h', $gz_data); // First 2 bytes should be divisible by 0x1F list(, $first_two_bytes) = unpack('n', $gz_data); if ($first_nibble === 0x08 && ($first_two_bytes % 0x1F) === 0) { $huffman_encoded = true; } if ($huffman_encoded) { $decompressed = @gzinflate(substr($gz_data, 2)); if ($decompressed !== false) { return $decompressed; } } if (substr($gz_data, 0, 4) === "\x50\x4b\x03\x04") { // ZIP file format header // Offset 6: 2 bytes, General-purpose field // Offset 26: 2 bytes, filename length // Offset 28: 2 bytes, optional field length // Offset 30: Filename field, followed by optional field, followed // immediately by data list(, $general_purpose_flag) = unpack('v', substr($gz_data, 6, 2)); // If the file has been compressed on the fly, 0x08 bit is set of // the general purpose field. We can use this to differentiate // between a compressed document, and a ZIP file $zip_compressed_on_the_fly = ((0x08 & $general_purpose_flag) === 0x08); if (!$zip_compressed_on_the_fly) { // Don't attempt to decode a compressed zip file return $gz_data; } // Determine the first byte of data, based on the above ZIP header // offsets: $first_file_start = array_sum(unpack('v2', substr($gz_data, 26, 4))); $decompressed = @gzinflate(substr($gz_data, 30 + $first_file_start)); if ($decompressed !== false) { return $decompressed; } return false; } // Finally fall back to straight gzinflate $decompressed = @gzinflate($gz_data); if ($decompressed !== false) { return $decompressed; } // Fallback for all above failing, not expected, but included for // debugging and preventing regressions and to track stats $decompressed = @gzinflate(substr($gz_data, 2)); if ($decompressed !== false) { return $decompressed; } return false; } } src/Cookie/Jar.php000064400000010413150211046430007764 0ustar00cookies = $cookies; } /** * Normalise cookie data into a \WpOrg\Requests\Cookie * * @param string|\WpOrg\Requests\Cookie $cookie Cookie header value, possibly pre-parsed (object). * @param string $key Optional. The name for this cookie. * @return \WpOrg\Requests\Cookie */ public function normalize_cookie($cookie, $key = '') { if ($cookie instanceof Cookie) { return $cookie; } return Cookie::parse($cookie, $key); } /** * Check if the given item exists * * @param string $offset Item key * @return boolean Does the item exist? */ #[ReturnTypeWillChange] public function offsetExists($offset) { return isset($this->cookies[$offset]); } /** * Get the value for the item * * @param string $offset Item key * @return string|null Item value (null if offsetExists is false) */ #[ReturnTypeWillChange] public function offsetGet($offset) { if (!isset($this->cookies[$offset])) { return null; } return $this->cookies[$offset]; } /** * Set the given item * * @param string $offset Item name * @param string $value Item value * * @throws \WpOrg\Requests\Exception On attempting to use dictionary as list (`invalidset`) */ #[ReturnTypeWillChange] public function offsetSet($offset, $value) { if ($offset === null) { throw new Exception('Object is a dictionary, not a list', 'invalidset'); } $this->cookies[$offset] = $value; } /** * Unset the given header * * @param string $offset The key for the item to unset. */ #[ReturnTypeWillChange] public function offsetUnset($offset) { unset($this->cookies[$offset]); } /** * Get an iterator for the data * * @return \ArrayIterator */ #[ReturnTypeWillChange] public function getIterator() { return new ArrayIterator($this->cookies); } /** * Register the cookie handler with the request's hooking system * * @param \WpOrg\Requests\HookManager $hooks Hooking system */ public function register(HookManager $hooks) { $hooks->register('requests.before_request', [$this, 'before_request']); $hooks->register('requests.before_redirect_check', [$this, 'before_redirect_check']); } /** * Add Cookie header to a request if we have any * * As per RFC 6265, cookies are separated by '; ' * * @param string $url * @param array $headers * @param array $data * @param string $type * @param array $options */ public function before_request($url, &$headers, &$data, &$type, &$options) { if (!$url instanceof Iri) { $url = new Iri($url); } if (!empty($this->cookies)) { $cookies = []; foreach ($this->cookies as $key => $cookie) { $cookie = $this->normalize_cookie($cookie, $key); // Skip expired cookies if ($cookie->is_expired()) { continue; } if ($cookie->domain_matches($url->host)) { $cookies[] = $cookie->format_for_header(); } } $headers['Cookie'] = implode('; ', $cookies); } } /** * Parse all cookies from a response and attach them to the response * * @param \WpOrg\Requests\Response $response Response as received. */ public function before_redirect_check(Response $response) { $url = $response->url; if (!$url instanceof Iri) { $url = new Iri($url); } $cookies = Cookie::parse_from_headers($response->headers, $url); $this->cookies = array_merge($this->cookies, $cookies); $response->cookies = $this; } } src/Session.php000064400000021623150211046430007467 0ustar00useragent = 'X';` * * @var array */ public $options = []; /** * Create a new session * * @param string|Stringable|null $url Base URL for requests * @param array $headers Default headers for requests * @param array $data Default data for requests * @param array $options Default options for requests * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $url argument is not a string, Stringable or null. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $headers argument is not an array. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $data argument is not an array. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. */ public function __construct($url = null, $headers = [], $data = [], $options = []) { if ($url !== null && InputValidator::is_string_or_stringable($url) === false) { throw InvalidArgument::create(1, '$url', 'string|Stringable|null', gettype($url)); } if (is_array($headers) === false) { throw InvalidArgument::create(2, '$headers', 'array', gettype($headers)); } if (is_array($data) === false) { throw InvalidArgument::create(3, '$data', 'array', gettype($data)); } if (is_array($options) === false) { throw InvalidArgument::create(4, '$options', 'array', gettype($options)); } $this->url = $url; $this->headers = $headers; $this->data = $data; $this->options = $options; if (empty($this->options['cookies'])) { $this->options['cookies'] = new Jar(); } } /** * Get a property's value * * @param string $name Property name. * @return mixed|null Property value, null if none found */ public function __get($name) { if (isset($this->options[$name])) { return $this->options[$name]; } return null; } /** * Set a property's value * * @param string $name Property name. * @param mixed $value Property value */ public function __set($name, $value) { $this->options[$name] = $value; } /** * Remove a property's value * * @param string $name Property name. */ public function __isset($name) { return isset($this->options[$name]); } /** * Remove a property's value * * @param string $name Property name. */ public function __unset($name) { unset($this->options[$name]); } /**#@+ * @see \WpOrg\Requests\Session::request() * @param string $url * @param array $headers * @param array $options * @return \WpOrg\Requests\Response */ /** * Send a GET request */ public function get($url, $headers = [], $options = []) { return $this->request($url, $headers, null, Requests::GET, $options); } /** * Send a HEAD request */ public function head($url, $headers = [], $options = []) { return $this->request($url, $headers, null, Requests::HEAD, $options); } /** * Send a DELETE request */ public function delete($url, $headers = [], $options = []) { return $this->request($url, $headers, null, Requests::DELETE, $options); } /**#@-*/ /**#@+ * @see \WpOrg\Requests\Session::request() * @param string $url * @param array $headers * @param array $data * @param array $options * @return \WpOrg\Requests\Response */ /** * Send a POST request */ public function post($url, $headers = [], $data = [], $options = []) { return $this->request($url, $headers, $data, Requests::POST, $options); } /** * Send a PUT request */ public function put($url, $headers = [], $data = [], $options = []) { return $this->request($url, $headers, $data, Requests::PUT, $options); } /** * Send a PATCH request * * Note: Unlike {@see \WpOrg\Requests\Session::post()} and {@see \WpOrg\Requests\Session::put()}, * `$headers` is required, as the specification recommends that should send an ETag * * @link https://tools.ietf.org/html/rfc5789 */ public function patch($url, $headers, $data = [], $options = []) { return $this->request($url, $headers, $data, Requests::PATCH, $options); } /**#@-*/ /** * Main interface for HTTP requests * * This method initiates a request and sends it via a transport before * parsing. * * @see \WpOrg\Requests\Requests::request() * * @param string $url URL to request * @param array $headers Extra headers to send with the request * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests * @param string $type HTTP request type (use \WpOrg\Requests\Requests constants) * @param array $options Options for the request (see {@see \WpOrg\Requests\Requests::request()}) * @return \WpOrg\Requests\Response * * @throws \WpOrg\Requests\Exception On invalid URLs (`nonhttp`) */ public function request($url, $headers = [], $data = [], $type = Requests::GET, $options = []) { $request = $this->merge_request(compact('url', 'headers', 'data', 'options')); return Requests::request($request['url'], $request['headers'], $request['data'], $type, $request['options']); } /** * Send multiple HTTP requests simultaneously * * @see \WpOrg\Requests\Requests::request_multiple() * * @param array $requests Requests data (see {@see \WpOrg\Requests\Requests::request_multiple()}) * @param array $options Global and default options (see {@see \WpOrg\Requests\Requests::request()}) * @return array Responses (either \WpOrg\Requests\Response or a \WpOrg\Requests\Exception object) * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $requests argument is not an array or iterable object with array access. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $options argument is not an array. */ public function request_multiple($requests, $options = []) { if (InputValidator::has_array_access($requests) === false || InputValidator::is_iterable($requests) === false) { throw InvalidArgument::create(1, '$requests', 'array|ArrayAccess&Traversable', gettype($requests)); } if (is_array($options) === false) { throw InvalidArgument::create(2, '$options', 'array', gettype($options)); } foreach ($requests as $key => $request) { $requests[$key] = $this->merge_request($request, false); } $options = array_merge($this->options, $options); // Disallow forcing the type, as that's a per request setting unset($options['type']); return Requests::request_multiple($requests, $options); } public function __wakeup() { throw new \LogicException( __CLASS__ . ' should never be unserialized' ); } /** * Merge a request's data with the default data * * @param array $request Request data (same form as {@see \WpOrg\Requests\Session::request_multiple()}) * @param boolean $merge_options Should we merge options as well? * @return array Request data */ protected function merge_request($request, $merge_options = true) { if ($this->url !== null) { $request['url'] = Iri::absolutize($this->url, $request['url']); $request['url'] = $request['url']->uri; } if (empty($request['headers'])) { $request['headers'] = []; } $request['headers'] = array_merge($this->headers, $request['headers']); if (empty($request['data'])) { if (is_array($this->data)) { $request['data'] = $this->data; } } elseif (is_array($request['data']) && is_array($this->data)) { $request['data'] = array_merge($this->data, $request['data']); } if ($merge_options === true) { $request['options'] = array_merge($this->options, $request['options']); // Disallow forcing the type, as that's a per request setting unset($request['options']['type']); } return $request; } } src/IdnaEncoder.php000064400000030223150211046430010213 0ustar00 0) { if ($position + $length > $strlen) { throw new Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character); } for ($position++; $remaining > 0; $position++) { $value = ord($input[$position]); // If it is invalid, count the sequence as invalid and reprocess the current byte: if (($value & 0xC0) !== 0x80) { throw new Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character); } --$remaining; $character |= ($value & 0x3F) << ($remaining * 6); } $position--; } if (// Non-shortest form sequences are invalid $length > 1 && $character <= 0x7F || $length > 2 && $character <= 0x7FF || $length > 3 && $character <= 0xFFFF // Outside of range of ucschar codepoints // Noncharacters || ($character & 0xFFFE) === 0xFFFE || $character >= 0xFDD0 && $character <= 0xFDEF || ( // Everything else not in ucschar $character > 0xD7FF && $character < 0xF900 || $character < 0x20 || $character > 0x7E && $character < 0xA0 || $character > 0xEFFFD ) ) { throw new Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character); } $codepoints[] = $character; } return $codepoints; } /** * RFC3492-compliant encoder * * @internal Pseudo-code from Section 6.3 is commented with "#" next to relevant code * * @param string $input UTF-8 encoded string to encode * @return string Punycode-encoded string * * @throws \WpOrg\Requests\Exception On character outside of the domain (never happens with Punycode) (`idna.character_outside_domain`) */ public static function punycode_encode($input) { $output = ''; // let n = initial_n $n = self::BOOTSTRAP_INITIAL_N; // let delta = 0 $delta = 0; // let bias = initial_bias $bias = self::BOOTSTRAP_INITIAL_BIAS; // let h = b = the number of basic code points in the input $h = 0; $b = 0; // see loop // copy them to the output in order $codepoints = self::utf8_to_codepoints($input); $extended = []; foreach ($codepoints as $char) { if ($char < 128) { // Character is valid ASCII // TODO: this should also check if it's valid for a URL $output .= chr($char); $h++; // Check if the character is non-ASCII, but below initial n // This never occurs for Punycode, so ignore in coverage // @codeCoverageIgnoreStart } elseif ($char < $n) { throw new Exception('Invalid character', 'idna.character_outside_domain', $char); // @codeCoverageIgnoreEnd } else { $extended[$char] = true; } } $extended = array_keys($extended); sort($extended); $b = $h; // [copy them] followed by a delimiter if b > 0 if (strlen($output) > 0) { $output .= '-'; } // {if the input contains a non-basic code point < n then fail} // while h < length(input) do begin $codepointcount = count($codepoints); while ($h < $codepointcount) { // let m = the minimum code point >= n in the input $m = array_shift($extended); //printf('next code point to insert is %s' . PHP_EOL, dechex($m)); // let delta = delta + (m - n) * (h + 1), fail on overflow $delta += ($m - $n) * ($h + 1); // let n = m $n = $m; // for each code point c in the input (in order) do begin for ($num = 0; $num < $codepointcount; $num++) { $c = $codepoints[$num]; // if c < n then increment delta, fail on overflow if ($c < $n) { $delta++; } elseif ($c === $n) { // if c == n then begin // let q = delta $q = $delta; // for k = base to infinity in steps of base do begin for ($k = self::BOOTSTRAP_BASE; ; $k += self::BOOTSTRAP_BASE) { // let t = tmin if k <= bias {+ tmin}, or // tmax if k >= bias + tmax, or k - bias otherwise if ($k <= ($bias + self::BOOTSTRAP_TMIN)) { $t = self::BOOTSTRAP_TMIN; } elseif ($k >= ($bias + self::BOOTSTRAP_TMAX)) { $t = self::BOOTSTRAP_TMAX; } else { $t = $k - $bias; } // if q < t then break if ($q < $t) { break; } // output the code point for digit t + ((q - t) mod (base - t)) $digit = (int) ($t + (($q - $t) % (self::BOOTSTRAP_BASE - $t))); $output .= self::digit_to_char($digit); // let q = (q - t) div (base - t) $q = (int) floor(($q - $t) / (self::BOOTSTRAP_BASE - $t)); } // end // output the code point for digit q $output .= self::digit_to_char($q); // let bias = adapt(delta, h + 1, test h equals b?) $bias = self::adapt($delta, $h + 1, $h === $b); // let delta = 0 $delta = 0; // increment h $h++; } // end } // end // increment delta and n $delta++; $n++; } // end return $output; } /** * Convert a digit to its respective character * * @link https://tools.ietf.org/html/rfc3492#section-5 * * @param int $digit Digit in the range 0-35 * @return string Single character corresponding to digit * * @throws \WpOrg\Requests\Exception On invalid digit (`idna.invalid_digit`) */ protected static function digit_to_char($digit) { // @codeCoverageIgnoreStart // As far as I know, this never happens, but still good to be sure. if ($digit < 0 || $digit > 35) { throw new Exception(sprintf('Invalid digit %d', $digit), 'idna.invalid_digit', $digit); } // @codeCoverageIgnoreEnd $digits = 'abcdefghijklmnopqrstuvwxyz0123456789'; return substr($digits, $digit, 1); } /** * Adapt the bias * * @link https://tools.ietf.org/html/rfc3492#section-6.1 * @param int $delta * @param int $numpoints * @param bool $firsttime * @return int|float New bias * * function adapt(delta,numpoints,firsttime): */ protected static function adapt($delta, $numpoints, $firsttime) { // if firsttime then let delta = delta div damp if ($firsttime) { $delta = floor($delta / self::BOOTSTRAP_DAMP); } else { // else let delta = delta div 2 $delta = floor($delta / 2); } // let delta = delta + (delta div numpoints) $delta += floor($delta / $numpoints); // let k = 0 $k = 0; // while delta > ((base - tmin) * tmax) div 2 do begin $max = floor(((self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN) * self::BOOTSTRAP_TMAX) / 2); while ($delta > $max) { // let delta = delta div (base - tmin) $delta = floor($delta / (self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN)); // let k = k + base $k += self::BOOTSTRAP_BASE; } // end // return k + (((base - tmin + 1) * delta) div (delta + skew)) return $k + floor(((self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN + 1) * $delta) / ($delta + self::BOOTSTRAP_SKEW)); } } src/Response/Headers.php000064400000006035150211046430011215 0ustar00data[$offset])) { return null; } return $this->flatten($this->data[$offset]); } /** * Set the given item * * @param string $offset Item name * @param string $value Item value * * @throws \WpOrg\Requests\Exception On attempting to use dictionary as list (`invalidset`) */ public function offsetSet($offset, $value) { if ($offset === null) { throw new Exception('Object is a dictionary, not a list', 'invalidset'); } if (is_string($offset)) { $offset = strtolower($offset); } if (!isset($this->data[$offset])) { $this->data[$offset] = []; } $this->data[$offset][] = $value; } /** * Get all values for a given header * * @param string $offset Name of the header to retrieve. * @return array|null Header values * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not valid as an array key. */ public function getValues($offset) { if (!is_string($offset) && !is_int($offset)) { throw InvalidArgument::create(1, '$offset', 'string|int', gettype($offset)); } if (is_string($offset)) { $offset = strtolower($offset); } if (!isset($this->data[$offset])) { return null; } return $this->data[$offset]; } /** * Flattens a value into a string * * Converts an array into a string by imploding values with a comma, as per * RFC2616's rules for folding headers. * * @param string|array $value Value to flatten * @return string Flattened value * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed argument is not a string or an array. */ public function flatten($value) { if (is_string($value)) { return $value; } if (is_array($value)) { return implode(',', $value); } throw InvalidArgument::create(1, '$value', 'string|array', gettype($value)); } /** * Get an iterator for the data * * Converts the internally stored values to a comma-separated string if there is more * than one value for a key. * * @return \ArrayIterator */ public function getIterator() { return new FilteredIterator($this->data, [$this, 'flatten']); } } src/Cookie.php000064400000036035150211046430007260 0ustar00name = $name; $this->value = $value; $this->attributes = $attributes; $default_flags = [ 'creation' => time(), 'last-access' => time(), 'persistent' => false, 'host-only' => true, ]; $this->flags = array_merge($default_flags, $flags); $this->reference_time = time(); if ($reference_time !== null) { $this->reference_time = $reference_time; } $this->normalize(); } /** * Get the cookie value * * Attributes and other data can be accessed via methods. */ public function __toString() { return $this->value; } /** * Check if a cookie is expired. * * Checks the age against $this->reference_time to determine if the cookie * is expired. * * @return boolean True if expired, false if time is valid. */ public function is_expired() { // RFC6265, s. 4.1.2.2: // If a cookie has both the Max-Age and the Expires attribute, the Max- // Age attribute has precedence and controls the expiration date of the // cookie. if (isset($this->attributes['max-age'])) { $max_age = $this->attributes['max-age']; return $max_age < $this->reference_time; } if (isset($this->attributes['expires'])) { $expires = $this->attributes['expires']; return $expires < $this->reference_time; } return false; } /** * Check if a cookie is valid for a given URI * * @param \WpOrg\Requests\Iri $uri URI to check * @return boolean Whether the cookie is valid for the given URI */ public function uri_matches(Iri $uri) { if (!$this->domain_matches($uri->host)) { return false; } if (!$this->path_matches($uri->path)) { return false; } return empty($this->attributes['secure']) || $uri->scheme === 'https'; } /** * Check if a cookie is valid for a given domain * * @param string $domain Domain to check * @return boolean Whether the cookie is valid for the given domain */ public function domain_matches($domain) { if (is_string($domain) === false) { return false; } if (!isset($this->attributes['domain'])) { // Cookies created manually; cookies created by Requests will set // the domain to the requested domain return true; } $cookie_domain = $this->attributes['domain']; if ($cookie_domain === $domain) { // The cookie domain and the passed domain are identical. return true; } // If the cookie is marked as host-only and we don't have an exact // match, reject the cookie if ($this->flags['host-only'] === true) { return false; } if (strlen($domain) <= strlen($cookie_domain)) { // For obvious reasons, the cookie domain cannot be a suffix if the passed domain // is shorter than the cookie domain return false; } if (substr($domain, -1 * strlen($cookie_domain)) !== $cookie_domain) { // The cookie domain should be a suffix of the passed domain. return false; } $prefix = substr($domain, 0, strlen($domain) - strlen($cookie_domain)); if (substr($prefix, -1) !== '.') { // The last character of the passed domain that is not included in the // domain string should be a %x2E (".") character. return false; } // The passed domain should be a host name (i.e., not an IP address). return !preg_match('#^(.+\.)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$#', $domain); } /** * Check if a cookie is valid for a given path * * From the path-match check in RFC 6265 section 5.1.4 * * @param string $request_path Path to check * @return boolean Whether the cookie is valid for the given path */ public function path_matches($request_path) { if (empty($request_path)) { // Normalize empty path to root $request_path = '/'; } if (!isset($this->attributes['path'])) { // Cookies created manually; cookies created by Requests will set // the path to the requested path return true; } if (is_scalar($request_path) === false) { return false; } $cookie_path = $this->attributes['path']; if ($cookie_path === $request_path) { // The cookie-path and the request-path are identical. return true; } if (strlen($request_path) > strlen($cookie_path) && substr($request_path, 0, strlen($cookie_path)) === $cookie_path) { if (substr($cookie_path, -1) === '/') { // The cookie-path is a prefix of the request-path, and the last // character of the cookie-path is %x2F ("/"). return true; } if (substr($request_path, strlen($cookie_path), 1) === '/') { // The cookie-path is a prefix of the request-path, and the // first character of the request-path that is not included in // the cookie-path is a %x2F ("/") character. return true; } } return false; } /** * Normalize cookie and attributes * * @return boolean Whether the cookie was successfully normalized */ public function normalize() { foreach ($this->attributes as $key => $value) { $orig_value = $value; if (is_string($key)) { $value = $this->normalize_attribute($key, $value); } if ($value === null) { unset($this->attributes[$key]); continue; } if ($value !== $orig_value) { $this->attributes[$key] = $value; } } return true; } /** * Parse an individual cookie attribute * * Handles parsing individual attributes from the cookie values. * * @param string $name Attribute name * @param string|int|bool $value Attribute value (string/integer value, or true if empty/flag) * @return mixed Value if available, or null if the attribute value is invalid (and should be skipped) */ protected function normalize_attribute($name, $value) { switch (strtolower($name)) { case 'expires': // Expiration parsing, as per RFC 6265 section 5.2.1 if (is_int($value)) { return $value; } $expiry_time = strtotime($value); if ($expiry_time === false) { return null; } return $expiry_time; case 'max-age': // Expiration parsing, as per RFC 6265 section 5.2.2 if (is_int($value)) { return $value; } // Check that we have a valid age if (!preg_match('/^-?\d+$/', $value)) { return null; } $delta_seconds = (int) $value; if ($delta_seconds <= 0) { $expiry_time = 0; } else { $expiry_time = $this->reference_time + $delta_seconds; } return $expiry_time; case 'domain': // Domains are not required as per RFC 6265 section 5.2.3 if (empty($value)) { return null; } // Domain normalization, as per RFC 6265 section 5.2.3 if ($value[0] === '.') { $value = substr($value, 1); } return $value; default: return $value; } } /** * Format a cookie for a Cookie header * * This is used when sending cookies to a server. * * @return string Cookie formatted for Cookie header */ public function format_for_header() { return sprintf('%s=%s', $this->name, $this->value); } /** * Format a cookie for a Set-Cookie header * * This is used when sending cookies to clients. This isn't really * applicable to client-side usage, but might be handy for debugging. * * @return string Cookie formatted for Set-Cookie header */ public function format_for_set_cookie() { $header_value = $this->format_for_header(); if (!empty($this->attributes)) { $parts = []; foreach ($this->attributes as $key => $value) { // Ignore non-associative attributes if (is_numeric($key)) { $parts[] = $value; } else { $parts[] = sprintf('%s=%s', $key, $value); } } $header_value .= '; ' . implode('; ', $parts); } return $header_value; } /** * Parse a cookie string into a cookie object * * Based on Mozilla's parsing code in Firefox and related projects, which * is an intentional deviation from RFC 2109 and RFC 2616. RFC 6265 * specifies some of this handling, but not in a thorough manner. * * @param string $cookie_header Cookie header value (from a Set-Cookie header) * @param string $name * @param int|null $reference_time * @return \WpOrg\Requests\Cookie Parsed cookie object * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $cookie_header argument is not a string. * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $name argument is not a string. */ public static function parse($cookie_header, $name = '', $reference_time = null) { if (is_string($cookie_header) === false) { throw InvalidArgument::create(1, '$cookie_header', 'string', gettype($cookie_header)); } if (is_string($name) === false) { throw InvalidArgument::create(2, '$name', 'string', gettype($name)); } $parts = explode(';', $cookie_header); $kvparts = array_shift($parts); if (!empty($name)) { $value = $cookie_header; } elseif (strpos($kvparts, '=') === false) { // Some sites might only have a value without the equals separator. // Deviate from RFC 6265 and pretend it was actually a blank name // (`=foo`) // // https://bugzilla.mozilla.org/show_bug.cgi?id=169091 $name = ''; $value = $kvparts; } else { list($name, $value) = explode('=', $kvparts, 2); } $name = trim($name); $value = trim($value); // Attribute keys are handled case-insensitively $attributes = new CaseInsensitiveDictionary(); if (!empty($parts)) { foreach ($parts as $part) { if (strpos($part, '=') === false) { $part_key = $part; $part_value = true; } else { list($part_key, $part_value) = explode('=', $part, 2); $part_value = trim($part_value); } $part_key = trim($part_key); $attributes[$part_key] = $part_value; } } return new static($name, $value, $attributes, [], $reference_time); } /** * Parse all Set-Cookie headers from request headers * * @param \WpOrg\Requests\Response\Headers $headers Headers to parse from * @param \WpOrg\Requests\Iri|null $origin URI for comparing cookie origins * @param int|null $time Reference time for expiration calculation * @return array * * @throws \WpOrg\Requests\Exception\InvalidArgument When the passed $origin argument is not null or an instance of the Iri class. */ public static function parse_from_headers(Headers $headers, $origin = null, $time = null) { $cookie_headers = $headers->getValues('Set-Cookie'); if (empty($cookie_headers)) { return []; } if ($origin !== null && !($origin instanceof Iri)) { throw InvalidArgument::create(2, '$origin', Iri::class . ' or null', gettype($origin)); } $cookies = []; foreach ($cookie_headers as $header) { $parsed = self::parse($header, '', $time); // Default domain/path attributes if (empty($parsed->attributes['domain']) && !empty($origin)) { $parsed->attributes['domain'] = $origin->host; $parsed->flags['host-only'] = true; } else { $parsed->flags['host-only'] = false; } $path_is_valid = (!empty($parsed->attributes['path']) && $parsed->attributes['path'][0] === '/'); if (!$path_is_valid && !empty($origin)) { $path = $origin->path; // Default path normalization as per RFC 6265 section 5.1.4 if (substr($path, 0, 1) !== '/') { // If the uri-path is empty or if the first character of // the uri-path is not a %x2F ("/") character, output // %x2F ("/") and skip the remaining steps. $path = '/'; } elseif (substr_count($path, '/') === 1) { // If the uri-path contains no more than one %x2F ("/") // character, output %x2F ("/") and skip the remaining // step. $path = '/'; } else { // Output the characters of the uri-path from the first // character up to, but not including, the right-most // %x2F ("/"). $path = substr($path, 0, strrpos($path, '/')); } $parsed->attributes['path'] = $path; } // Reject invalid cookie domains if (!empty($origin) && !$parsed->domain_matches($origin->host)) { continue; } $cookies[$parsed->name] = $parsed; } return $cookies; } } src/HookManager.php000064400000001305150211046430010232 0ustar000 is executed later */ public function register($hook, $callback, $priority = 0); /** * Dispatch a message * * @param string $hook Hook name * @param array $parameters Parameters to pass to callbacks * @return boolean Successfulness */ public function dispatch($hook, $parameters = []); } src/Exception/error_log000064400000004006150212234520011202 0ustar00[16-May-2025 23:27:38 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/ArgumentCount.php:20 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/ArgumentCount.php on line 20 [16-May-2025 23:27:44 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http.php:18 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http.php on line 18 [16-May-2025 23:29:39 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Transport.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Transport.php on line 17 [17-May-2025 00:41:44 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/ArgumentCount.php:20 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/ArgumentCount.php on line 20 [17-May-2025 00:41:51 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http.php:18 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http.php on line 18 [17-May-2025 00:43:55 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Transport.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Transport.php on line 17 src/Exception/Transport/error_log000064400000001326150212234520013200 0ustar00[16-May-2025 23:29:40 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Transport" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Transport/Curl.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Transport/Curl.php on line 17 [17-May-2025 00:44:00 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Transport" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Transport/Curl.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Transport/Curl.php on line 17 src/Exception/Http/error_log000064400000056134150212234520012132 0ustar00[16-May-2025 23:27:46 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status304.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status304.php on line 17 [16-May-2025 23:27:49 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status305.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status305.php on line 17 [16-May-2025 23:27:54 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status306.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status306.php on line 17 [16-May-2025 23:27:56 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status400.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status400.php on line 17 [16-May-2025 23:27:58 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status401.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status401.php on line 17 [16-May-2025 23:28:00 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status402.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status402.php on line 17 [16-May-2025 23:28:08 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status403.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status403.php on line 17 [16-May-2025 23:28:10 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status404.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status404.php on line 17 [16-May-2025 23:28:16 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status405.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status405.php on line 17 [16-May-2025 23:28:23 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status406.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status406.php on line 17 [16-May-2025 23:28:24 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status407.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status407.php on line 17 [16-May-2025 23:28:27 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status408.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status408.php on line 17 [16-May-2025 23:28:29 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status409.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status409.php on line 17 [16-May-2025 23:28:30 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status410.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status410.php on line 17 [16-May-2025 23:28:37 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status411.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status411.php on line 17 [16-May-2025 23:28:38 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status412.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status412.php on line 17 [16-May-2025 23:28:40 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status413.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status413.php on line 17 [16-May-2025 23:28:42 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status414.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status414.php on line 17 [16-May-2025 23:28:43 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status415.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status415.php on line 17 [16-May-2025 23:28:49 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status416.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status416.php on line 17 [16-May-2025 23:28:50 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status417.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status417.php on line 17 [16-May-2025 23:28:51 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status418.php:21 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status418.php on line 21 [16-May-2025 23:28:55 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status428.php:21 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status428.php on line 21 [16-May-2025 23:28:57 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status429.php:21 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status429.php on line 21 [16-May-2025 23:29:00 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status431.php:21 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status431.php on line 21 [16-May-2025 23:29:06 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status500.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status500.php on line 17 [16-May-2025 23:29:11 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status501.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status501.php on line 17 [16-May-2025 23:29:12 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status502.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status502.php on line 17 [16-May-2025 23:29:16 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status503.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status503.php on line 17 [16-May-2025 23:29:18 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status504.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status504.php on line 17 [16-May-2025 23:29:19 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status505.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status505.php on line 17 [16-May-2025 23:29:21 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status511.php:21 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status511.php on line 21 [16-May-2025 23:29:24 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/StatusUnknown.php:18 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/StatusUnknown.php on line 18 [17-May-2025 00:41:59 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status304.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status304.php on line 17 [17-May-2025 00:42:06 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status305.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status305.php on line 17 [17-May-2025 00:42:08 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status306.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status306.php on line 17 [17-May-2025 00:42:10 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status400.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status400.php on line 17 [17-May-2025 00:42:13 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status401.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status401.php on line 17 [17-May-2025 00:42:16 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status402.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status402.php on line 17 [17-May-2025 00:42:20 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status403.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status403.php on line 17 [17-May-2025 00:42:21 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status404.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status404.php on line 17 [17-May-2025 00:42:26 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status405.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status405.php on line 17 [17-May-2025 00:42:28 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status406.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status406.php on line 17 [17-May-2025 00:42:37 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status407.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status407.php on line 17 [17-May-2025 00:42:41 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status408.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status408.php on line 17 [17-May-2025 00:42:42 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status409.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status409.php on line 17 [17-May-2025 00:42:45 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status410.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status410.php on line 17 [17-May-2025 00:42:52 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status411.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status411.php on line 17 [17-May-2025 00:42:57 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status412.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status412.php on line 17 [17-May-2025 00:42:58 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status413.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status413.php on line 17 [17-May-2025 00:43:01 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status414.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status414.php on line 17 [17-May-2025 00:43:03 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status415.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status415.php on line 17 [17-May-2025 00:43:07 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status416.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status416.php on line 17 [17-May-2025 00:43:08 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status417.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status417.php on line 17 [17-May-2025 00:43:13 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status418.php:21 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status418.php on line 21 [17-May-2025 00:43:14 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status428.php:21 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status428.php on line 21 [17-May-2025 00:43:15 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status429.php:21 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status429.php on line 21 [17-May-2025 00:43:21 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status431.php:21 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status431.php on line 21 [17-May-2025 00:43:25 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status500.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status500.php on line 17 [17-May-2025 00:43:32 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status501.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status501.php on line 17 [17-May-2025 00:43:37 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status502.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status502.php on line 17 [17-May-2025 00:43:39 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status503.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status503.php on line 17 [17-May-2025 00:43:41 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status504.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status504.php on line 17 [17-May-2025 00:43:42 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status505.php:17 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status505.php on line 17 [17-May-2025 00:43:45 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status511.php:21 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/Status511.php on line 21 [17-May-2025 00:43:50 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Exception\Http" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/StatusUnknown.php:18 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Exception/Http/StatusUnknown.php on line 18 src/error_log000064400000001202150212234520007237 0ustar00[16-May-2025 23:29:48 America/New_York] PHP Fatal error: Uncaught Error: Interface "WpOrg\Requests\HookManager" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Hooks.php:19 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Hooks.php on line 19 [17-May-2025 00:44:04 America/New_York] PHP Fatal error: Uncaught Error: Interface "WpOrg\Requests\HookManager" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Hooks.php:19 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Hooks.php on line 19 src/Proxy/error_log000064400000001212150212234520010361 0ustar00[16-May-2025 23:30:10 America/New_York] PHP Fatal error: Uncaught Error: Interface "WpOrg\Requests\Proxy" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Proxy/Http.php:24 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Proxy/Http.php on line 24 [17-May-2025 00:44:22 America/New_York] PHP Fatal error: Uncaught Error: Interface "WpOrg\Requests\Proxy" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Proxy/Http.php:24 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Proxy/Http.php on line 24 src/Transport/error_log000064400000002530150212234530011241 0ustar00[16-May-2025 23:30:48 America/New_York] PHP Fatal error: Uncaught Error: Interface "WpOrg\Requests\Transport" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Transport/Curl.php:25 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Transport/Curl.php on line 25 [16-May-2025 23:30:55 America/New_York] PHP Fatal error: Uncaught Error: Interface "WpOrg\Requests\Transport" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Transport/Fsockopen.php:25 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Transport/Fsockopen.php on line 25 [17-May-2025 00:44:46 America/New_York] PHP Fatal error: Uncaught Error: Interface "WpOrg\Requests\Transport" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Transport/Curl.php:25 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Transport/Curl.php on line 25 [17-May-2025 00:44:51 America/New_York] PHP Fatal error: Uncaught Error: Interface "WpOrg\Requests\Transport" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Transport/Fsockopen.php:25 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Transport/Fsockopen.php on line 25 src/Auth/error_log000064400000001210150212234530010140 0ustar00[16-May-2025 23:27:13 America/New_York] PHP Fatal error: Uncaught Error: Interface "WpOrg\Requests\Auth" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Auth/Basic.php:23 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Auth/Basic.php on line 23 [17-May-2025 00:41:09 America/New_York] PHP Fatal error: Uncaught Error: Interface "WpOrg\Requests\Auth" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Auth/Basic.php:23 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Auth/Basic.php on line 23 src/Response/error_log000064400000001322150212234530011041 0ustar00[16-May-2025 23:30:31 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Utility\CaseInsensitiveDictionary" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Response/Headers.php:20 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Response/Headers.php on line 20 [17-May-2025 00:44:33 America/New_York] PHP Fatal error: Uncaught Error: Class "WpOrg\Requests\Utility\CaseInsensitiveDictionary" not found in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Response/Headers.php:20 Stack trace: #0 {main} thrown in /home/abhiramc/public_html/gymnastics/wp-includes/Requests/src/Response/Headers.php on line 20