*/ 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:----dNj5zoaoi7tO+wD5XcD64NVa8CC0PhpIcCvwlvPiRYVUpc0e1f+cD2OHX6sCEb0jwEQDJQ5vY+0UQTSdsI1FxMfUD5CCDDjr/7MfatowiG1tuc/OF2MWYsPUrh934Xb2Lef1hcQfk11PUOf554P1O/ZkjQ+ZfuxYbDzqcNORA4ZkvuA5PLKvO/n2OaZOuZJ6yfAEzxbq20lmL4JkFGtW4uFzHwGCGUHg+kbD6k9vVNBkSlgtC7+11/fQaaOZirPmQxvh1RXmpovEG2mR2piMRhAw4epneMg/o31RmidVyr5t6+83KhTdFOAeRhfiDYHyFpUUIYUjuKZ5wV320RjJUcmlf6OXyUuf4tRmi02CjmxawadZjWAujqoWq+NJ8CErO4dpldF+sQsvmjzM6OuKpmIz5TnKOmhKvTODXX61DwvutvHHRMcT7MlUYqgSq0xiIykVg7kF7hdZU3Dd6epIJIwOEBe1m6/oBvukrHlvxOpLDCn43HTndfU7L/OlkP/1TkiZFbt7lKXNfOdwwhmSOqeeoOuedgXO4pFfPhKf5Sh6/NqxcgCaTfNaTJUjghDSagqjsXms/UM8pU6ZslR6Xd0H6mwUk2cCS+P2MNvDUD4vTsGsYtH1X5ad7ixJGdTYGEtjiTNHfflD/a+gTpje2NPF/vjnlX8siHfV3NQz0GI=----ATTACHMENT:----MjEzNTQzMDI5OTI0OTEwOSA2MDE0MzczNzA4NzYxNjUzIDYxODEzNTcwMTMzNDMxMjM=