@@ -24,15 +24,17 @@ class Typo3ValetDriver extends ValetDriver
2424 | Forbidden URI Patterns
2525 |--------------------------------------------------------------------------
2626 |
27- | All of these patterns won't be publicly available from your web server.
28- | Instead, the server will throw a 403 forbidden response, if you try
29- | to access these files via the HTTP layer. Use regex syntax here.
27+ | All of these patterns won't be accessible from your web server. Instead,
28+ | the server will throw a 403 forbidden response, if you try to access
29+ | these files via the HTTP layer. Use regex syntax here and escape @ .
3030 |
3131 */
3232 protected $ forbiddenUriPatterns = [
3333 '_(recycler|temp)_/ ' ,
3434 '^/(typo3conf/ext|typo3/sysext|typo3/ext)/[^/]+/(Resources/Private|Tests)/ ' ,
35- '\.(htaccess|gitkeep|gitignore) ' ,
35+ '^/typo3/.+\.map$ ' ,
36+ '^/typo3temp/var/ ' ,
37+ '\.(htaccess|gitkeep|gitignore)$ ' ,
3638 ];
3739
3840 /**
@@ -62,18 +64,44 @@ public function serves($sitePath, $siteName, $uri)
6264 */
6365 public function isStaticFile ($ sitePath , $ siteName , $ uri )
6466 {
65- $ uri = $ this ->isVersionNumberInFilename ($ sitePath . $ this ->documentRoot . $ uri , $ uri );
67+ // May the file contains a cache busting version string like filename.12345678.css
68+ // If that is the case, the file cannot be found on disk, so remove the version
69+ // identifier before retrying below.
70+ if (!$ this ->isActualFile ($ filePath = $ sitePath . $ this ->documentRoot . $ uri ))
71+ {
72+ $ uri = preg_replace ("@^(.+)\.(\d+)\.(js|css|png|jpg|gif|gzip)$@ " , "$1.$3 " , $ uri );
73+ }
6674
67- if (file_exists ($ filePath = $ sitePath . $ this ->documentRoot . $ uri )
68- && ! is_dir ($ filePath )
69- && pathinfo ($ filePath )['extension ' ] !== 'php ' )
75+ // Now that any possible version string is cleared from the filename, the resulting
76+ // URI should be a valid file on disc. So assemble the absolut file name with the
77+ // same schema as above and if it exists, authorize access and return its path.
78+ if ($ this ->isActualFile ($ filePath = $ sitePath . $ this ->documentRoot . $ uri ))
7079 {
71- $ this ->authorizeAccess ($ uri );
72- return $ filePath ;
80+ return $ this ->isAccessAuthorized ($ uri ) ? $ filePath : false ;
7381 }
82+
83+ // This file cannot be found in the current project and thus cannot be served.
7484 return false ;
7585 }
7686
87+ /**
88+ * Determines if the given URI is blacklisted so that access is prevented.
89+ *
90+ * @param string $uri
91+ * @return boolean
92+ */
93+ private function isAccessAuthorized ($ uri )
94+ {
95+ foreach ($ this ->forbiddenUriPatterns as $ forbiddenUriPattern )
96+ {
97+ if (preg_match ("@ $ forbiddenUriPattern@ " , $ uri ))
98+ {
99+ return false ;
100+ }
101+ }
102+ return true ;
103+ }
104+
77105 /**
78106 * Get the fully resolved path to the application's front controller.
79107 * This can be the currently requested PHP script, a folder that
@@ -86,12 +114,14 @@ public function isStaticFile($sitePath, $siteName, $uri)
86114 */
87115 public function frontControllerPath ($ sitePath , $ siteName , $ uri )
88116 {
89- $ this ->directLoginToInstallTool ($ uri );
90- $ this ->authorizeAccess ($ uri );
117+ // without modifying the URI, redirect if necessary
118+ $ this ->handleRedirectBackendShorthandUris ($ uri );
119+
120+ // from now on, remove trailing / for convenience for all the following join operations
91121 $ uri = rtrim ($ uri , '/ ' );
92- $ absoluteFilePath = $ sitePath . $ this ->documentRoot . $ uri ;
93122
94- if (file_exists ($ absoluteFilePath ))
123+ // try to find the responsible script file for the requested folder / script URI
124+ if (file_exists ($ absoluteFilePath = $ sitePath . $ this ->documentRoot . $ uri ))
95125 {
96126 if (is_dir ($ absoluteFilePath ))
97127 {
@@ -107,7 +137,7 @@ public function frontControllerPath($sitePath, $siteName, $uri)
107137 return $ absoluteFilePath . '/index.html ' ;
108138 }
109139 }
110- else if (pathinfo ($ absoluteFilePath)[ ' extension ' ] === 'php ' )
140+ else if (pathinfo ($ absoluteFilePath, PATHINFO_EXTENSION ) === 'php ' )
111141 {
112142 // this file can be served directly
113143 return $ this ->serveScript ($ sitePath , $ siteName , $ uri );
@@ -118,79 +148,50 @@ public function frontControllerPath($sitePath, $siteName, $uri)
118148 return $ this ->serveScript ($ sitePath , $ siteName , '/index.php ' );
119149 }
120150
151+ /**
152+ * Direct access to installtool via domain.dev/typo3/install/ will be redirected to
153+ * sysext install script. domain.dev/typo3 will be redirected to /typo3/, because
154+ * the generated JavaScript URIs on the login screen would be broken on /typo3.
155+ *
156+ * @param string $uri
157+ */
158+ private function handleRedirectBackendShorthandUris ($ uri )
159+ {
160+ if (rtrim ($ uri , '/ ' ) === '/typo3/install ' )
161+ {
162+ header ('Location: /typo3/sysext/install/Start/Install.php ' );
163+ die ();
164+ }
165+
166+ if ($ uri === '/typo3 ' )
167+ {
168+ header ('Location: /typo3/ ' );
169+ die ();
170+ }
171+ }
172+
121173 /**
122174 * Configures the $_SERVER globals for serving the script at
123175 * the specified URI and returns it absolute file path.
124176 *
125177 * @param string $sitePath
126178 * @param string $siteName
127179 * @param string $uri
180+ * @param string $script
128181 * @return string
129182 */
130183 private function serveScript ($ sitePath , $ siteName , $ uri )
131184 {
132- $ absoluteDocumentRoot = $ sitePath . $ this ->documentRoot ;
133- $ absoluteFilePath = $ absoluteDocumentRoot . $ uri ;
185+ $ docroot = $ sitePath . $ this ->documentRoot ;
186+ $ abspath = $ docroot . $ uri ;
134187
135188 $ _SERVER ['SERVER_NAME ' ] = $ siteName . '.dev ' ;
136- $ _SERVER ['DOCUMENT_ROOT ' ] = $ absoluteDocumentRoot ;
189+ $ _SERVER ['DOCUMENT_ROOT ' ] = $ docroot ;
137190 $ _SERVER ['DOCUMENT_URI ' ] = $ uri ;
138- $ _SERVER ['SCRIPT_FILENAME ' ] = $ absoluteFilePath ;
191+ $ _SERVER ['SCRIPT_FILENAME ' ] = $ abspath ;
139192 $ _SERVER ['SCRIPT_NAME ' ] = $ uri ;
140193 $ _SERVER ['PHP_SELF ' ] = $ uri ;
141194
142- return $ absoluteFilePath ;
143- }
144-
145- /**
146- * Interrupts execution with a 403 FORBIDDEN if the requested URI is on
147- * the global blacklist of system files that should not be served.
148- *
149- * @param string $uri
150- */
151- private function authorizeAccess ($ uri )
152- {
153- foreach ($ this ->forbiddenUriPatterns as $ forbiddenUri )
154- {
155- if (preg_match ("@ $ forbiddenUri@ " , $ uri ))
156- {
157- header ('HTTP/1.0 403 Forbidden ' );
158- die ("You are forbidden to see $ uri! " );
159- }
160- }
161- }
162-
163-
164- /**
165- * Rule for versioned static files, configured through:
166- * - $GLOBALS['TYPO3_CONF_VARS']['BE']['versionNumberInFilename']
167- * - $GLOBALS['TYPO3_CONF_VARS']['FE']['versionNumberInFilename']
168- *
169- * @param string $filePath
170- * @param string $uri
171- * @return string $uri
172- */
173- private function isVersionNumberInFilename ($ filePath , $ uri ) {
174- if ( ! file_exists ($ filePath ) &&
175- preg_match ("/^(.+)\.(\d+)\.(php|js|css|png|jpg|gif|gzip)$/ " , $ uri )
176- ) {
177- return preg_replace ("/^(.+)\.(\d+)\.(php|js|css|png|jpg|gif|gzip)$/ " , "$1.$3 " , $ uri );
178- }
179-
180- return $ uri ;
181- }
182-
183- /**
184- * Direct access to installtool via domain.dev/typo3/install/
185- * Will be redirected to the sysext install script
186- *
187- * @param string $uri
188- */
189- private function directLoginToInstallTool ($ uri ) {
190- if (preg_match ("/^\/typo3\/install$/ " , rtrim ($ uri )))
191- {
192- header ('Location: /typo3/sysext/install/Start/Install.php ' );
193- die ();
194- }
195+ return $ abspath ;
195196 }
196197}
0 commit comments