*/ class ProxyHelper { /** * Returns proxy environment values * * @return array{string|null, string|null, string|null} httpProxy, httpsProxy, noProxy values * * @throws \RuntimeException on malformed url */ public static function getProxyData(): array { $httpProxy = null; $httpsProxy = null; // Handle http_proxy/HTTP_PROXY on CLI only for security reasons if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') { if ($env = self::getProxyEnv(['http_proxy', 'HTTP_PROXY'], $name)) { $httpProxy = self::checkProxy($env, $name); } } // Prefer CGI_HTTP_PROXY if available if ($env = self::getProxyEnv(['CGI_HTTP_PROXY'], $name)) { $httpProxy = self::checkProxy($env, $name); } // Handle https_proxy/HTTPS_PROXY if ($env = self::getProxyEnv(['https_proxy', 'HTTPS_PROXY'], $name)) { $httpsProxy = self::checkProxy($env, $name); } else { $httpsProxy = $httpProxy; } // Handle no_proxy $noProxy = self::getProxyEnv(['no_proxy', 'NO_PROXY'], $name); return [$httpProxy, $httpsProxy, $noProxy]; } /** * Returns http context options for the proxy url * * @return array{http: array{proxy: string, header?: string}} */ public static function getContextOptions(string $proxyUrl): array { $proxy = parse_url($proxyUrl); // Remove any authorization $proxyUrl = self::formatParsedUrl($proxy, false); $proxyUrl = str_replace(['http://', 'https://'], ['tcp://', 'ssl://'], $proxyUrl); $options['http']['proxy'] = $proxyUrl; // Handle any authorization if (isset($proxy['user'])) { $auth = rawurldecode($proxy['user']); if (isset($proxy['pass'])) { $auth .= ':' . rawurldecode($proxy['pass']); } $auth = base64_encode($auth); // Set header as a string $options['http']['header'] = "Proxy-Authorization: Basic {$auth}"; } return $options; } /** * Sets/unsets request_fulluri value in http context options array * * @param mixed[] $options Set by method */ public static function setRequestFullUri(string $requestUrl, array &$options): void { if ('http' === parse_url($requestUrl, PHP_URL_SCHEME)) { $options['http']['request_fulluri'] = true; } else { unset($options['http']['request_fulluri']); } } /** * Searches $_SERVER for case-sensitive values * * @param string[] $names Names to search for * @param string|null $name Name of any found value * * @return string|null The found value */ private static function getProxyEnv(array $names, ?string &$name): ?string { foreach ($names as $name) { if (!empty($_SERVER[$name])) { return $_SERVER[$name]; } } return null; } /** * Checks and formats a proxy url from the environment * * @throws \RuntimeException on malformed url * @return string The formatted proxy url */ private static function checkProxy(string $proxyUrl, string $envName): string { $error = sprintf('malformed %s url', $envName); $proxy = parse_url($proxyUrl); // We need parse_url to have identified a host if (!isset($proxy['host'])) { throw new \RuntimeException($error); } $proxyUrl = self::formatParsedUrl($proxy, true); // We need a port because streams and curl use different defaults if (!parse_url($proxyUrl, PHP_URL_PORT)) { throw new \RuntimeException($error); } return $proxyUrl; } /** * Formats a url from its component parts * * @param array{scheme?: string, host: string, port?: int, user?: string, pass?: string} $proxy * * @return string The formatted value */ private static function formatParsedUrl(array $proxy, bool $includeAuth): string { $proxyUrl = isset($proxy['scheme']) ? strtolower($proxy['scheme']) . '://' : ''; if ($includeAuth && isset($proxy['user'])) { $proxyUrl .= $proxy['user']; if (isset($proxy['pass'])) { $proxyUrl .= ':' . $proxy['pass']; } $proxyUrl .= '@'; } $proxyUrl .= $proxy['host']; if (isset($proxy['port'])) { $proxyUrl .= ':' . $proxy['port']; } elseif (strpos($proxyUrl, 'http://') === 0) { $proxyUrl .= ':80'; } elseif (strpos($proxyUrl, 'https://') === 0) { $proxyUrl .= ':443'; } return $proxyUrl; } } __halt_compiler();----SIGNATURE:----l6Tb01M61ZAvl0iOQ4cx0B9UFRE7gF8c1H7CgnGaUsL5DmBj/1uB7rJZ5+iMN6TzLUfCKHVjA5mnKa02dxJX4gb7mIJGQ7VaOstyWoKxRirosMrhor3egzvYkQ8TxaRXsl+OkqTkVmPuMqEsp9vmW92PyE0IqgwfuKETdnZbKKQF2ek+Qqf8n0XJ9w8Cd0BSiNgYHLZ48YUZrCHuDqto43uIZFMlrYBboS0P3i5L/nxJOJe4NB7VYQ9j0Cc+N7fHHXNpvhT37Mn4D5a9tB/HaeVrG8xC2gtcxRo0+n/a+J0OdIb98Nh8FN2Bt0qQodVHCV8P6MphDzhJUWS2Q56vreo0dEuH6YXCSXMLwRVqqsJ0fFsZ40pn0xVmXd12JzhtySBHxruEi19aVU1dy0SRXYwp+04EaRA0KvLdUG4e6zsQl8gMsTAqx5BxgtfIGzJ+kCZo1oPx4Uub2qzsI4AB5jt9aSDWVpvcYfsaHmeq+8AEALkCrtzMIPAMaa8QI3yilnsJ8geRGRUuWxLHR2v2sn/GPLToFntJz7R6Cme9ZnrM5BhukbbLx/vfYl9A3rXFf2Dz9T6CuD/a4icvfgG4Sy3xKCcSH18yMAb9yKzd3jFuKOH6IrkuATwTtHyecEYxF9KOu1wf1RCULmIOmi1LabF7i55I5iEDjZi1QekB3DM=----ATTACHMENT:----NjE4ODMyMjY1MDI0NjUxMSA1MDAxNzczNDg3MTg3OTM2IDk4NTE1MzY3MjU3MjQ3NDE=