💾 Archived View for code.lanterne.chilliet.eu › vendor › mcmic › gemini-server › src › Files › Reque… captured on 2023-05-24 at 17:51:49.
⬅️ Previous capture (2021-12-17)
-=-=-=-=-=-=-
<?php declare(strict_types=1); namespace MCMic\Gemini\Files; use MCMic\Gemini; class RequestHandler extends Gemini\RequestHandler { protected string $rootPath; /** * @var array<string> */ protected array $filePatterns; protected ?string $title = null; protected string $lang = ''; /** * @param array<string> $filePatterns */ public function __construct(string $host, string $certPath, string $rootPath, array $filePatterns, ?string $title = null, string $lang = '') { parent::__construct($host, $certPath); $realRootPath = realpath($rootPath); if ($realRootPath !== false) { $this->rootPath = $realRootPath; } else { $this->rootPath = $rootPath; } $this->filePatterns = $filePatterns; $this->title = $title; $this->lang = $lang; } /** * @throws \MCMic\Gemini\Exception */ public function handle(Gemini\Request $request): Gemini\Response { $path = $request->path ?? '/'; $path = substr($path, 1); $files = []; chdir($this->rootPath); foreach ($this->filePatterns as $pattern) { $glob = glob($pattern); if ($glob !== false) { $files = array_merge($files, $glob); } } $files = array_unique($files); $lang = $this->lang; if (is_dir($this->rootPath . '/' . $path)) { if (is_file($this->rootPath . '/' . $path . '/index.gmi')) { $path .= '/index.gmi'; } elseif (is_file($this->rootPath . '/' . $path . '/index.php')) { ob_start(); include($this->rootPath . '/' . $path . '/index.php'); $content = ob_get_contents(); ob_end_clean(); if (!is_string($content)) { throw new Gemini\Exception('', 42); } return new Gemini\Response\Success($content, 'text/gemini', $lang); } else { return new Gemini\Response\Success($this->buildIndex($path, $files), 'text/gemini', $lang); } } elseif (!in_array($path, $files, true)) { throw new Gemini\Exception('File not found', 51); } $content = file_get_contents($this->rootPath . '/' . $path); if ($content !== false) { if (static::str_ends_with($path, '.gmi')) { $mimetype = 'text/gemini'; if (preg_match('/\.([0-9a-z]{1,8}([-,][0-9a-z]{1,8})*)\.gmi$/i', $path, $m) === 1) { $lang = $m[1]; } } else { $mimetype = mime_content_type($this->rootPath . '/' . $path); if ($mimetype === false) { $mimetype = 'text/plain'; } } return new Gemini\Response\Success($content, $mimetype); } else { throw new Gemini\Exception('Could not open ' . $path, 59); } } /** * @param array<string> $files * @throws \MCMic\Gemini\Exception */ protected function buildIndex(string $path, array $files): string { if (isset($this->title)) { $output = '# ' . $this->title . "\r\n"; $output .= "\r\n"; if ($path != '') { $output = '## ' . '/' . $path . "\r\n"; $output .= "\r\n"; } } else { $output = '# ' . '/' . $path . "\r\n"; $output .= "\r\n"; } $found = false; foreach ($files as $file) { if (($path === '') || static::str_starts_with($file, $path . '/')) { $found = true; $output .= '=> ' . Gemini\Request::urlEncode('/' . $file) . ' ' . $file . "\r\n"; } } if ($found) { return $output; } else { throw new Gemini\Exception('File not found', 51); } } /** * From https://github.com/symfony/polyfill/blob/main/src/Php80/Php80.php * By Fabien Potencier <fabien@symfony.com> * License MIT */ public static function str_starts_with(string $haystack, string $needle): bool { return 0 === \strncmp($haystack, $needle, \strlen($needle)); } /** * From https://github.com/symfony/polyfill/blob/main/src/Php80/Php80.php * By Fabien Potencier <fabien@symfony.com> * License MIT */ public static function str_ends_with(string $haystack, string $needle): bool { return '' === $needle || ('' !== $haystack && 0 === \substr_compare($haystack, $needle, -\strlen($needle))); } }