proxyUrl = $GLOBALS['cfg']['ProxyUrl']; $this->proxyUser = $GLOBALS['cfg']['ProxyUser']; $this->proxyPass = $GLOBALS['cfg']['ProxyPass']; } public static function setProxySettingsFromEnv(): void { $httpProxy = getenv('http_proxy'); $urlInfo = parse_url((string) $httpProxy); if (PHP_SAPI !== 'cli' || ! is_array($urlInfo)) { return; } $GLOBALS['cfg']['ProxyUrl'] = ($urlInfo['host'] ?? '') . (isset($urlInfo['port']) ? ':' . $urlInfo['port'] : ''); $GLOBALS['cfg']['ProxyUser'] = $urlInfo['user'] ?? ''; $GLOBALS['cfg']['ProxyPass'] = $urlInfo['pass'] ?? ''; } /** * Returns information with regards to handling the http request * * @param array $context Data about the context for which * to http request is sent * * @return array of updated context information */ private function handleContext(array $context) { if (strlen($this->proxyUrl) > 0) { $context['http'] = [ 'proxy' => $this->proxyUrl, 'request_fulluri' => true, ]; if (strlen($this->proxyUser) > 0) { $auth = base64_encode($this->proxyUser . ':' . $this->proxyPass); $context['http']['header'] = 'Proxy-Authorization: Basic ' . $auth . "\r\n"; } } return $context; } /** * Creates HTTP request using curl * * @param mixed $response HTTP response * @param int $httpStatus HTTP response status code * @param bool $returnOnlyStatus If set to true, the method would only return response status * * @return string|bool|null */ private function response( $response, $httpStatus, $returnOnlyStatus ) { if ($httpStatus == 404) { return false; } if ($httpStatus != 200) { return null; } if ($returnOnlyStatus) { return true; } return $response; } /** * Creates HTTP request using curl * * @param string $url Url to send the request * @param string $method HTTP request method (GET, POST, PUT, DELETE, etc) * @param bool $returnOnlyStatus If set to true, the method would only return response status * @param mixed $content Content to be sent with HTTP request * @param string $header Header to be set for the HTTP request * * @return string|bool|null */ private function curl( $url, $method, $returnOnlyStatus = false, $content = null, $header = '' ) { $curlHandle = curl_init($url); if ($curlHandle === false) { return null; } $curlStatus = 1; if (strlen($this->proxyUrl) > 0) { $curlStatus &= (int) curl_setopt($curlHandle, CURLOPT_PROXY, $this->proxyUrl); if (strlen($this->proxyUser) > 0) { $curlStatus &= (int) curl_setopt( $curlHandle, CURLOPT_PROXYUSERPWD, $this->proxyUser . ':' . $this->proxyPass ); } } $curlStatus &= (int) curl_setopt($curlHandle, CURLOPT_USERAGENT, 'phpMyAdmin'); if ($method !== 'GET') { $curlStatus &= (int) curl_setopt($curlHandle, CURLOPT_CUSTOMREQUEST, $method); } if ($header) { $curlStatus &= (int) curl_setopt($curlHandle, CURLOPT_HTTPHEADER, [$header]); } if ($method === 'POST') { $curlStatus &= (int) curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $content); } $curlStatus &= (int) curl_setopt($curlHandle, CURLOPT_SSL_VERIFYHOST, 2); $curlStatus &= (int) curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, true); $caPathOrFile = CaBundle::getSystemCaRootBundlePath(); if (is_dir($caPathOrFile)) { $curlStatus &= (int) curl_setopt($curlHandle, CURLOPT_CAPATH, $caPathOrFile); } else { $curlStatus &= (int) curl_setopt($curlHandle, CURLOPT_CAINFO, $caPathOrFile); } $curlStatus &= (int) curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, true); $curlStatus &= (int) curl_setopt($curlHandle, CURLOPT_FOLLOWLOCATION, 0); $curlStatus &= (int) curl_setopt($curlHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); $curlStatus &= (int) curl_setopt($curlHandle, CURLOPT_TIMEOUT, 10); $curlStatus &= (int) curl_setopt($curlHandle, CURLOPT_CONNECTTIMEOUT, 10); if (! $curlStatus) { return null; } $response = @curl_exec($curlHandle); if ($response === false) { return null; } $httpStatus = curl_getinfo($curlHandle, CURLINFO_HTTP_CODE); return $this->response($response, $httpStatus, $returnOnlyStatus); } /** * Creates HTTP request using file_get_contents * * @param string $url Url to send the request * @param string $method HTTP request method (GET, POST, PUT, DELETE, etc) * @param bool $returnOnlyStatus If set to true, the method would only return response status * @param mixed $content Content to be sent with HTTP request * @param string $header Header to be set for the HTTP request * * @return string|bool|null */ private function fopen( $url, $method, $returnOnlyStatus = false, $content = null, $header = '' ) { $context = [ 'http' => [ 'method' => $method, 'request_fulluri' => true, 'timeout' => 10, 'user_agent' => 'phpMyAdmin', 'header' => 'Accept: */*', ], 'ssl' => [ 'verify_peer' => true, 'verify_peer_name' => true, ], ]; if ($header) { $context['http']['header'] .= "\n" . $header; } if ($method === 'POST') { $context['http']['content'] = $content; } $caPathOrFile = CaBundle::getSystemCaRootBundlePath(); if (is_dir($caPathOrFile)) { $context['ssl']['capath'] = $caPathOrFile; } else { $context['ssl']['cafile'] = $caPathOrFile; } $context = $this->handleContext($context); $response = @file_get_contents( $url, false, stream_context_create($context) ); if (! isset($http_response_header)) { return null; } preg_match('#HTTP/[0-9\.]+\s+([0-9]+)#', $http_response_header[0], $out); $httpStatus = intval($out[1]); return $this->response($response, $httpStatus, $returnOnlyStatus); } /** * Creates HTTP request * * @param string $url Url to send the request * @param string $method HTTP request method (GET, POST, PUT, DELETE, etc) * @param bool $returnOnlyStatus If set to true, the method would only return response status * @param mixed $content Content to be sent with HTTP request * @param string $header Header to be set for the HTTP request * * @return string|bool|null */ public function create( $url, $method, $returnOnlyStatus = false, $content = null, $header = '' ) { if (function_exists('curl_init')) { return $this->curl($url, $method, $returnOnlyStatus, $content, $header); } if (ini_get('allow_url_fopen')) { return $this->fopen($url, $method, $returnOnlyStatus, $content, $header); } return null; } }