*/ class ProxyManager { /** @var ?string */ private $error = null; /** @var array{http: ?string, https: ?string} */ private $fullProxy; /** @var array{http: ?string, https: ?string} */ private $safeProxy; /** @var array{http: array{options: mixed[]|null}, https: array{options: mixed[]|null}} */ private $streams; /** @var bool */ private $hasProxy; /** @var ?string */ private $info = null; /** @var ?NoProxyPattern */ private $noProxyHandler = null; /** @var ?ProxyManager */ private static $instance = null; private function __construct() { $this->fullProxy = $this->safeProxy = [ 'http' => null, 'https' => null, ]; $this->streams['http'] = $this->streams['https'] = [ 'options' => null, ]; $this->hasProxy = false; $this->initProxyData(); } public static function getInstance(): ProxyManager { if (!self::$instance) { self::$instance = new self(); } return self::$instance; } /** * Clears the persistent instance */ public static function reset(): void { self::$instance = null; } /** * Returns a RequestProxy instance for the request url * * @param non-empty-string $requestUrl */ public function getProxyForRequest(string $requestUrl): RequestProxy { if ($this->error) { throw new TransportException('Unable to use a proxy: '.$this->error); } $scheme = parse_url($requestUrl, PHP_URL_SCHEME) ?: 'http'; $proxyUrl = ''; $options = []; $formattedProxyUrl = ''; if ($this->hasProxy && in_array($scheme, ['http', 'https'], true) && $this->fullProxy[$scheme]) { if ($this->noProxy($requestUrl)) { $formattedProxyUrl = 'excluded by no_proxy'; } else { $proxyUrl = $this->fullProxy[$scheme]; $options = $this->streams[$scheme]['options']; ProxyHelper::setRequestFullUri($requestUrl, $options); $formattedProxyUrl = $this->safeProxy[$scheme]; } } return new RequestProxy($proxyUrl, $options, $formattedProxyUrl); } /** * Returns true if a proxy is being used * * @return bool If false any error will be in $message */ public function isProxying(): bool { return $this->hasProxy; } /** * Returns proxy configuration info which can be shown to the user * * @return string|null Safe proxy URL or an error message if setting up proxy failed or null if no proxy was configured */ public function getFormattedProxy(): ?string { return $this->hasProxy ? $this->info : $this->error; } /** * Initializes proxy values from the environment */ private function initProxyData(): void { try { [$httpProxy, $httpsProxy, $noProxy] = ProxyHelper::getProxyData(); } catch (\RuntimeException $e) { $this->error = $e->getMessage(); return; } $info = []; if ($httpProxy) { $info[] = $this->setData($httpProxy, 'http'); } if ($httpsProxy) { $info[] = $this->setData($httpsProxy, 'https'); } if ($this->hasProxy) { $this->info = implode(', ', $info); if ($noProxy) { $this->noProxyHandler = new NoProxyPattern($noProxy); } } } /** * Sets initial data * * @param non-empty-string $url Proxy url * @param 'http'|'https' $scheme Environment variable scheme * * @return non-empty-string */ private function setData($url, $scheme): string { $safeProxy = Url::sanitize($url); $this->fullProxy[$scheme] = $url; $this->safeProxy[$scheme] = $safeProxy; $this->streams[$scheme]['options'] = ProxyHelper::getContextOptions($url); $this->hasProxy = true; return sprintf('%s=%s', $scheme, $safeProxy); } /** * Returns true if a url matches no_proxy value */ private function noProxy(string $requestUrl): bool { return $this->noProxyHandler && $this->noProxyHandler->test($requestUrl); } } __halt_compiler();----SIGNATURE:----cp5VuRitGY/9hNDFNDn6NjGY0axmN4Pihxf3lj4RulCOZX+hrRg53n7JraXzytin5wWuz5BhGw4Q26Yu3AAvgYaADnbgRbLIB65JTGlnr4MfJQWoLyBuU8ZpLKHPw/SeCbO8s9D8B4TDe8lrYPupEqqUhNJLc1YPBV1ZgM7oWjJ9UEJFgwN3RVkA6OTlBuD8Nb/CYmElgM8K1ODUuTf9fUlP6y325DjZKbHK9lqzhO4rFtM5w2apzHwg8MbyMWXML42yRp8KBoSoBmup/hHwAjoIqRc0Pf6pdZwiMt7fDh9j//PkfgAwgf/BzAmoBZvAXLzX6hQed1/m/pMn1u5v/feXDNr79X9gktARo84mGokKTFikNAek1rAjk2l3Jc5HZjpodJsS/WeTM/TEtIe23507aLwgW1wZNFed/D19zTxlGgEkdp9creKPDRfjFLA621z1So/D9Vh+HNB/z+cU0v0c8NGWojeTX5ifaK0Jwbq3Iqi0W99rmSktMpKDCzhN8tcs2yUQ+77X2Cfm5wZcTV/EUcOwisQA2pZnLFYOi7+zp5sUTmXJVnpddMbKZy90ndm2iHABOGIvcQc+AWZcQvUI6s83RlN9Ai64Vn7ZHIxdEUZSyy1ZQg4s7wgMq5ofrH/cT0Q4d5zYObWJKmMn+FHqX/sdPbIazx8K3EiGoUk=----ATTACHMENT:----NTkxNDIwODY3ODM1MjQwMSAzNzcyMjkwMDEzNzQ2NjI1IDg5NTMwNzk2NjQ1OTg0ODE=