From 0758366430e623c7169b6e7bf66773477c72da56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Goetz?= Date: Thu, 8 Jun 2017 23:07:18 +0200 Subject: [PATCH] Rely on symfony's HttpFoundation to handle requests. Fixes weird bugs --- composer.json | 3 +- composer.lock | 55 +++++++++++++++++- libs/Server/MimeType.php | 81 -------------------------- libs/Server/Server.php | 119 ++++++++++++++++----------------------- 4 files changed, 103 insertions(+), 155 deletions(-) delete mode 100644 libs/Server/MimeType.php diff --git a/composer.json b/composer.json index d2089ca..d5a3d73 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,8 @@ "symfony/finder": "~3.0", "webuni/commonmark-table-extension": "0.6.*", "webuni/front-matter": "^1.0.0", - "symfony/process": "^3.1" + "symfony/process": "^3.1", + "symfony/http-foundation": "^3.3" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 5229711..ebfdbed 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "89c196ac8c5858ac075e9a7eccadbf1a", + "content-hash": "177814363edbcc8b16c48140e2b439ef", "packages": [ { "name": "guzzlehttp/guzzle", @@ -621,6 +621,59 @@ "homepage": "https://symfony.com", "time": "2017-06-01T21:01:25+00:00" }, + { + "name": "symfony/http-foundation", + "version": "v3.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "80eb5a1f968448b77da9e8b2c0827f6e8d767846" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/80eb5a1f968448b77da9e8b2c0827f6e8d767846", + "reference": "80eb5a1f968448b77da9e8b2c0827f6e8d767846", + "shasum": "" + }, + "require": { + "php": ">=5.5.9", + "symfony/polyfill-mbstring": "~1.1" + }, + "require-dev": { + "symfony/expression-language": "~2.8|~3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony HttpFoundation Component", + "homepage": "https://symfony.com", + "time": "2017-06-05T13:06:51+00:00" + }, { "name": "symfony/polyfill-mbstring", "version": "v1.3.0", diff --git a/libs/Server/MimeType.php b/libs/Server/MimeType.php deleted file mode 100644 index be71729..0000000 --- a/libs/Server/MimeType.php +++ /dev/null @@ -1,81 +0,0 @@ - - * @see http://www.php.net/mime_content_type - */ -class MimeType -{ - /** - * @var array - */ - protected static $mimeTypes = [ - 'txt' => 'text/plain', - 'htm' => 'text/html', - 'html' => 'text/html', - 'php' => 'text/html', - 'css' => 'text/css', - 'js' => 'application/javascript', - 'json' => 'application/json', - 'xml' => 'application/xml', - 'swf' => 'application/x-shockwave-flash', - 'flv' => 'video/x-flv', - // Images - 'png' => 'image/png', - 'jpe' => 'image/jpeg', - 'jpeg' => 'image/jpeg', - 'jpg' => 'image/jpeg', - 'gif' => 'image/gif', - 'bmp' => 'image/bmp', - 'ico' => 'image/vnd.microsoft.icon', - 'tiff' => 'image/tiff', - 'tif' => 'image/tiff', - 'svg' => 'image/svg+xml', - 'svgz' => 'image/svg+xml', - // Archives - 'zip' => 'application/zip', - 'rar' => 'application/x-rar-compressed', - 'exe' => 'application/x-msdownload', - 'msi' => 'application/x-msdownload', - 'cab' => 'application/vnd.ms-cab-compressed', - // Audio/video - 'mp3' => 'audio/mpeg', - 'qt' => 'video/quicktime', - 'mov' => 'video/quicktime', - // Adobe - 'pdf' => 'application/pdf', - 'psd' => 'image/vnd.adobe.photoshop', - 'ai' => 'application/postscript', - 'eps' => 'application/postscript', - 'ps' => 'application/postscript', - // MS Office - 'doc' => 'application/msword', - 'rtf' => 'application/rtf', - 'xls' => 'application/vnd.ms-excel', - 'ppt' => 'application/vnd.ms-powerpoint', - // Open Office - 'odt' => 'application/vnd.oasis.opendocument.text', - 'ods' => 'application/vnd.oasis.opendocument.spreadsheet', - ]; - /** - * @param $filename - * @return string - */ - public static function get($filename) - { - $pathInfo = pathinfo($filename); - $extension = strtolower($pathInfo['extension']); - if (array_key_exists($extension, self::$mimeTypes)) { - return self::$mimeTypes[$extension]; - } elseif (function_exists('finfo_open') && is_file($filename)) { - $finfo = finfo_open(FILEINFO_MIME); - $mimetype = finfo_file($finfo, $filename); - finfo_close($finfo); - - return $mimetype; - } else { - return 'application/octet-stream'; - } - } -} diff --git a/libs/Server/Server.php b/libs/Server/Server.php index af94c92..f154387 100755 --- a/libs/Server/Server.php +++ b/libs/Server/Server.php @@ -1,18 +1,21 @@ handle(); } catch (NotFoundException $e) { - http_response_code(404); $page = new ErrorPage('An error occured', $e->getMessage(), $daux->getParams()); } - if ($page instanceof RawPage) { - header('Content-type: ' . MimeType::get($page->getFile())); - - // Transfer file in 1024 byte chunks to save memory usage. - if ($fd = fopen($page->getFile(), 'rb')) { - while (!feof($fd)) { - echo fread($fd, 1024); - } - fclose($fd); - } - - return; - } - - if ($page instanceof ComputedRawPage) { - header('Content-type: ' . MimeType::get($page->getFilename())); - } else { - header('Content-type: text/html; charset=utf-8'); - } - - echo $page->getContent(); + $server->createResponse($page)->prepare($server->request)->send(); } public function __construct(Daux $daux) { $this->daux = $daux; - $this->host = $_SERVER['HTTP_HOST']; + $this->request = Request::createFromGlobals(); + $this->base_url = $this->request->getHttpHost() . $this->request->getBaseUrl() . "/"; + } - // The path has a special treatment on windows, revert the slashes - $dir = dirname($_SERVER['PHP_SELF']); - $this->base_url = $_SERVER['HTTP_HOST'] . (DIRECTORY_SEPARATOR == '\\' ? str_replace('\\', '/', $dir) : $dir); + /** + * Create a temporary file with the file suffix, for mime type detection. + * + * @param string $postfix + * @return string + */ + function getTemporaryFile($postfix) { + $sysFileName = tempnam(sys_get_temp_dir(), 'daux'); + if ($sysFileName === false) { + throw new \RuntimeException("Could not create temporary file"); + } - $t = strrpos($this->base_url, '/index.php'); - if ($t != false) { - $this->base_url = substr($this->base_url, 0, $t); + $newFileName = $sysFileName . $postfix; + if ($sysFileName == $newFileName) { + return $sysFileName; } - if (substr($this->base_url, -1) !== '/') { - $this->base_url .= '/'; + + if (DIRECTORY_SEPARATOR == '\\' ? rename($sysFileName, $newFileName) : link($sysFileName, $newFileName)) { + return $newFileName; } + + throw new \RuntimeException("Could not create temporary file"); + } + + /** + * @param Page $page + * @return Response + */ + public function createResponse(Page $page) { + if ($page instanceof RawPage) { + return new BinaryFileResponse($page->getFile()); + } + + if ($page instanceof ComputedRawPage) { + $file = $this->getTemporaryFile($page->getFilename()); + file_put_contents($file, $page->getContent()); + return new BinaryFileResponse($file); + } + + return new Response($page->getContent(), $page instanceof ErrorPage ? 404 : 200); } /** @@ -95,8 +108,6 @@ class Server { $params = $this->daux->getParams(); - $params['host'] = $this->host; - DauxHelper::rebaseConfiguration($params, '//' . $this->base_url); $params['base_page'] = '//' . $this->base_url; if (!$this->daux->options['live']['clean_urls']) { @@ -120,14 +131,13 @@ class Server { $this->params = $this->getParams(); - $request = $this->getRequest(); - $request = urldecode($request); + $request = substr($this->request->getRequestUri(), 1); if (substr($request, 0, 7) == 'themes/') { return $this->serveTheme(substr($request, 6)); } - if ($request == 'index_page') { + if ($request == '') { $request = $this->daux->tree->getIndexPage()->getUri(); } @@ -177,39 +187,4 @@ class Server return $this->daux->getGenerator()->generateOne($file, $this->params); } - - public function getRequest() - { - if (isset($_SERVER['PATH_INFO'])) { - $uri = $_SERVER['PATH_INFO']; - } elseif (isset($_SERVER['REQUEST_URI'])) { - $uri = $_SERVER['REQUEST_URI']; - if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0) { - $uri = substr($uri, strlen($_SERVER['SCRIPT_NAME'])); - } elseif (strpos($uri, dirname($_SERVER['SCRIPT_NAME'])) === 0) { - $uri = substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME']))); - } - if (strncmp($uri, '?/', 2) === 0) { - $uri = substr($uri, 2); - } - $parts = preg_split('#\?#i', $uri, 2); - $uri = $parts[0]; - if (isset($parts[1])) { - $_SERVER['QUERY_STRING'] = $parts[1]; - parse_str($_SERVER['QUERY_STRING'], $_GET); - } else { - $_SERVER['QUERY_STRING'] = ''; - $_GET = []; - } - $uri = parse_url($uri, PHP_URL_PATH); - } else { - return false; - } - $uri = str_replace(['//', '../'], '/', trim($uri, '/')); - if ($uri == '') { - $uri = 'index_page'; - } - - return $uri; - } }