aboutsummaryrefslogtreecommitdiff
path: root/srcs/phpmyadmin/libraries/classes/Utils/HttpRequest.php
diff options
context:
space:
mode:
Diffstat (limited to 'srcs/phpmyadmin/libraries/classes/Utils/HttpRequest.php')
-rw-r--r--srcs/phpmyadmin/libraries/classes/Utils/HttpRequest.php260
1 files changed, 260 insertions, 0 deletions
diff --git a/srcs/phpmyadmin/libraries/classes/Utils/HttpRequest.php b/srcs/phpmyadmin/libraries/classes/Utils/HttpRequest.php
new file mode 100644
index 0000000..fa846ed
--- /dev/null
+++ b/srcs/phpmyadmin/libraries/classes/Utils/HttpRequest.php
@@ -0,0 +1,260 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Hold the PhpMyAdmin\Utils\HttpRequest class
+ *
+ * @package PhpMyAdmin
+ */
+declare(strict_types=1);
+
+namespace PhpMyAdmin\Utils;
+
+/**
+ * Handles HTTP requests
+ *
+ * @package PhpMyAdmin
+ */
+class HttpRequest
+{
+ private $proxyUrl;
+ private $proxyUser;
+ private $proxyPass;
+
+ /**
+ * Constructor
+ */
+ public function __construct()
+ {
+ global $cfg;
+
+ $this->proxyUrl = $cfg['ProxyUrl'];
+ $this->proxyUser = $cfg['ProxyUser'];
+ $this->proxyPass = $cfg['ProxyPass'];
+ }
+
+ /**
+ * 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|null|bool
+ */
+ 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
+ * @param int $ssl SSL mode to use
+ *
+ * @return string|null|bool
+ */
+ private function curl(
+ $url,
+ $method,
+ $returnOnlyStatus = false,
+ $content = null,
+ $header = '',
+ $ssl = 0
+ ) {
+ $curlHandle = curl_init($url);
+ if ($curlHandle === false) {
+ return null;
+ }
+ $curlStatus = true;
+ if (strlen($this->proxyUrl) > 0) {
+ $curlStatus &= curl_setopt($curlHandle, CURLOPT_PROXY, $this->proxyUrl);
+ if (strlen($this->proxyUser) > 0) {
+ $curlStatus &= curl_setopt(
+ $curlHandle,
+ CURLOPT_PROXYUSERPWD,
+ $this->proxyUser . ':' . $this->proxyPass
+ );
+ }
+ }
+ $curlStatus &= curl_setopt($curlHandle, CURLOPT_USERAGENT, 'phpMyAdmin');
+
+ if ($method != "GET") {
+ $curlStatus &= curl_setopt($curlHandle, CURLOPT_CUSTOMREQUEST, $method);
+ }
+ if ($header) {
+ $curlStatus &= curl_setopt($curlHandle, CURLOPT_HTTPHEADER, [$header]);
+ }
+
+ if ($method == "POST") {
+ $curlStatus &= curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $content);
+ }
+
+ $curlStatus &= curl_setopt($curlHandle, CURLOPT_SSL_VERIFYHOST, '2');
+ $curlStatus &= curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, '1');
+
+ /**
+ * Configure ISRG Root X1 to be able to verify Let's Encrypt SSL
+ * certificates even without properly configured curl in PHP.
+ *
+ * See https://letsencrypt.org/certificates/
+ */
+ $certsDir = ROOT_PATH . 'libraries/certs/';
+ /* See code below for logic */
+ if ($ssl == CURLOPT_CAPATH) {
+ $curlStatus &= curl_setopt($curlHandle, CURLOPT_CAPATH, $certsDir);
+ } elseif ($ssl == CURLOPT_CAINFO) {
+ $curlStatus &= curl_setopt($curlHandle, CURLOPT_CAINFO, $certsDir . 'cacert.pem');
+ }
+
+ $curlStatus &= curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, true);
+ $curlStatus &= curl_setopt($curlHandle, CURLOPT_FOLLOWLOCATION, 0);
+ $curlStatus &= curl_setopt($curlHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
+ $curlStatus &= curl_setopt($curlHandle, CURLOPT_TIMEOUT, 10);
+ $curlStatus &= curl_setopt($curlHandle, CURLOPT_CONNECTTIMEOUT, 10);
+
+ if (! $curlStatus) {
+ return null;
+ }
+ $response = @curl_exec($curlHandle);
+ if ($response === false) {
+ /*
+ * In case of SSL verification failure let's try configuring curl
+ * certificate verification. Unfortunately it is tricky as setting
+ * options incompatible with PHP build settings can lead to failure.
+ *
+ * So let's rather try the options one by one.
+ *
+ * 1. Try using system SSL storage.
+ * 2. Try setting CURLOPT_CAINFO.
+ * 3. Try setting CURLOPT_CAPATH.
+ * 4. Fail.
+ */
+ if (curl_getinfo($curlHandle, CURLINFO_SSL_VERIFYRESULT) != 0) {
+ if ($ssl == 0) {
+ return $this->curl($url, $method, $returnOnlyStatus, $content, $header, CURLOPT_CAINFO);
+ } elseif ($ssl == CURLOPT_CAINFO) {
+ return $this->curl($url, $method, $returnOnlyStatus, $content, $header, CURLOPT_CAPATH);
+ }
+ }
+ 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|null|bool
+ */
+ private function fopen(
+ $url,
+ $method,
+ $returnOnlyStatus = false,
+ $content = null,
+ $header = ''
+ ) {
+ $context = [
+ 'http' => [
+ 'method' => $method,
+ 'request_fulluri' => true,
+ 'timeout' => 10,
+ 'user_agent' => 'phpMyAdmin',
+ 'header' => "Accept: */*",
+ ],
+ ];
+ if ($header) {
+ $context['http']['header'] .= "\n" . $header;
+ }
+ if ($method == "POST") {
+ $context['http']['content'] = $content;
+ }
+ $context = $this->handleContext($context);
+ $response = @file_get_contents(
+ $url,
+ false,
+ stream_context_create($context)
+ );
+ if (isset($http_response_header)) {
+ preg_match("#HTTP/[0-9\.]+\s+([0-9]+)#", $http_response_header[0], $out);
+ $httpStatus = intval($out[1]);
+ return $this->response($response, $httpStatus, $returnOnlyStatus);
+ }
+ return null;
+ }
+
+ /**
+ * 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|null|bool
+ */
+ public function create(
+ $url,
+ $method,
+ $returnOnlyStatus = false,
+ $content = null,
+ $header = ''
+ ) {
+ if (function_exists('curl_init')) {
+ return $this->curl($url, $method, $returnOnlyStatus, $content, $header);
+ } elseif (ini_get('allow_url_fopen')) {
+ return $this->fopen($url, $method, $returnOnlyStatus, $content, $header);
+ }
+ return null;
+ }
+}