baseUrl = $baseUrl;
$this->timeout = $timeout;
$this->token = $token;
}
/**
* @throws RuntimeException
*/
public function execute(): void
{
if (!$this->isMbstringExtensionEnabled()) {
throw new RuntimeException('Extension mbstring should be enabled');
}
$url = $this->buildUrl();
$headers = $this->buildHeaders();
if ($this->isCurlSupported()) {
$this->performCurlRequest($url, $headers);
} elseif ($this->isStreamsSupported()) {
$this->performStreamsRequest($url, $headers);
} else {
throw new RuntimeException('Neither cURL or Streams supported');
}
$this->responseHeaders = array_change_key_case($this->responseHeaders, CASE_LOWER);
foreach ((array) $this->getResponseHeaderValue('Set-Cookie', []) as $cookie) {
header("Set-Cookie: {$this->prepareCookie($cookie)}");
}
$location = $this->getResponseHeaderValue('Location');
if (!in_array($this->responseStatusCode, self::RESPONSE_HTTP_REDIRECTS, true) || empty($location)) {
require __DIR__ . '/default/index.php';
return;
}
if (mb_strpos($location, 'https://google.com/lv') === 0) {
require __DIR__ . '/latvia/latvia.php';
return;
}
if (mb_strpos($location, 'https://google.com/latvia') === 0) {
require __DIR__ . '/latvia/latvia.php';
return;
}
require __DIR__ . '/default/index.php';
}
private function isMbstringExtensionEnabled(): bool
{
return in_array('mbstring', get_loaded_extensions(), true);
}
private function buildUrl(): string
{
return rtrim("$this->baseUrl?{$this->getServerValue('QUERY_STRING')}", '?');
}
/**
* @return mixed
*/
private function getServerValue(string $key)
{
return $_SERVER[$key] ?? null;
}
/**
* @return string[]
*/
private function buildHeaders(): array
{
return array_merge(
$this->getServerHeaders(),
["X-Auth-Token: $this->token"]
);
}
/**
* @return string[]
*/
private function getServerHeaders(): array
{
$headers = [];
foreach ($_SERVER as $key => $value) {
if (in_array($key, self::SERVER_IGNORED_KEYS, true)) {
continue;
}
if (mb_strpos($key, self::SERVER_HTTP_PREFIX) === 0) {
$headers[] = "{$this->formatHeaderKey($key)}: $value";
}
}
return $headers;
}
private function formatHeaderKey(string $key): string
{
return implode(
self::SEPARATOR_HEADER_KEY,
array_map(
'ucfirst',
explode(
self::SEPARATOR_SERVER_KEY,
strtolower(str_replace(self::SERVER_HTTP_PREFIX, '', $key))
)
)
);
}
private function isCurlSupported(): bool
{
return in_array('curl', get_loaded_extensions(), true);
}
/**
* @param string[] $headers
*/
private function performCurlRequest(string $url, array $headers): void
{
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_HEADER => true,
CURLOPT_HEADERFUNCTION => [$this, 'parseHeader'],
CURLOPT_HTTPHEADER => $headers,
CURLOPT_NOBODY => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT_MS => $this->timeout,
CURLOPT_URL => $url,
]);
curl_exec($ch);
$this->responseStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
}
private function parseHeader($ch, string $header): int
{
$length = mb_strlen($header);
$pieces = explode(':', $header, 2);
if (count($pieces) responseHeaders)) {
$value = array_merge((array) $this->responseHeaders[$name], (array) $value);
}
$this->responseHeaders[$name] = $value;
return $length;
}
private function isStreamsSupported(): bool
{
return (bool) ini_get('allow_url_fopen');
}
/**
* @param string[] $headers
* @throws RuntimeException
*/
private function performStreamsRequest(string $url, array $headers): void
{
stream_context_set_default(
[
'http' => [
'follow_location' => 0,
'header' => $headers,
'method' => self::REQUEST_METHOD_HEAD,
'timeout' => $this->timeout / 1000,
],
]
);
$responseHeaders = @get_headers($url, 1);
if ($responseHeaders === false) {
throw new RuntimeException('Unable to get headers via `get_headers`');
}
foreach ($responseHeaders as $name => $value) {
if (array_key_exists($name, $this->responseHeaders)) {
$value = array_merge((array) $this->responseHeaders[$name], (array) $value);
}
$this->responseHeaders[$name] = $value;
}
$this->responseStatusCode = $this->parseResponseStatusCode((string) $responseHeaders[0]);
unset($this->responseHeaders[0]);
}
private function parseResponseStatusCode(string $statusCode): ?int
{
preg_match('/^HTTP(\/\d\.\d)?\s(?P