Fix AutoloadGenerator to work on MediaWiki-Vagrant (again)
authorBryan Davis <bd808@wikimedia.org>
Sat, 20 Dec 2014 19:05:29 +0000 (12:05 -0700)
committerUmherirrender <umherirrender_de.wp@web.de>
Sat, 20 Dec 2014 21:45:43 +0000 (21:45 +0000)
The patch set from I5d502b5 re-introduced the use of realpath() within
AutoloadGenerator::readFile() as part of a set of changes to ensure that
path separators are normalized across Unix and Windows systems. As noted
previously in I4623b3d, the use of realpath() in this function will
cause fatal exceptions to be thrown when a file such as
LocalSettings.php is a symlink to a file outside to $IP.

This patch separates the path normalization functionality from
realpath() expansion and uses only the path normalization component
within AutoloadGenerator::readFile(). It also introduces a cautionary
comment in AutoloadGenerator::readFile() that will hopefully keep
realpath() from being reintroduced there.

Change-Id: I4923dfa8370a7bd6077f42ff4c437d7293fdad66

includes/utils/AutoloadGenerator.php

index 6149a23..0d0907b 100644 (file)
@@ -50,24 +50,13 @@ class AutoloadGenerator {
                if ( !is_array( $flags ) ) {
                        $flags = array( $flags );
                }
-               $this->basepath = self::platformAgnosticRealpath( $basepath );
+               $this->basepath = self::normalizePathSeparator( realpath( $basepath ) );
                $this->collector = new ClassCollector;
                if ( in_array( 'local', $flags ) ) {
                        $this->variableName = 'wgAutoloadLocalClasses';
                }
        }
 
-       /**
-        * Wrapper for realpath() that returns the same results (using forward
-        * slashes) on both Windows and *nix.
-        *
-        * @param string $path Parameter to realpath()
-        * @return string
-        */
-       protected static function platformAgnosticRealpath( $path ) {
-               return str_replace( '\\', '/', realpath( $path ) );
-       }
-
        /**
         * Force a class to be autoloaded from a specific path, regardless of where
         * or if it was detected.
@@ -76,7 +65,7 @@ class AutoloadGenerator {
         * @param string $inputPath Full path to the file containing the class
         */
        public function forceClassPath( $fqcn, $inputPath ) {
-               $path = self::platformAgnosticRealpath( $inputPath );
+               $path = self::normalizePathSeparator( realpath( $inputPath ) );
                if ( !$path ) {
                        throw new \Exception( "Invalid path: $inputPath" );
                }
@@ -92,7 +81,10 @@ class AutoloadGenerator {
         * @param string $inputPath Path to a php file to find classes within
         */
        public function readFile( $inputPath ) {
-               $inputPath = self::platformAgnosticRealpath( $inputPath );
+               // NOTE: do NOT expand $inputPath using realpath(). It is perfectly
+               // reasonable for LocalSettings.php and similiar files to be symlinks
+               // to files that are outside of $this->basepath.
+               $inputPath = self::normalizePathSeparator( $inputPath );
                $len = strlen( $this->basepath );
                if ( substr( $inputPath, 0, $len ) !== $this->basepath ) {
                        throw new \Exception( "Path is not within basepath: $inputPath" );
@@ -112,7 +104,7 @@ class AutoloadGenerator {
         */
        public function readDir( $dir ) {
                $it = new RecursiveDirectoryIterator(
-                       self::platformAgnosticRealpath( $dir ) );
+                       self::normalizePathSeparator( realpath( $dir ) ) );
                $it = new RecursiveIteratorIterator( $it );
 
                foreach ( $it as $path => $file ) {
@@ -183,6 +175,16 @@ global \${$this->variableName};
 EOD
                );
        }
+
+       /**
+        * Ensure that Unix-style path separators ("/") are used in the path.
+        *
+        * @param string $path
+        * @return string
+        */
+       protected static function normalizePathSeparator( $path ) {
+               return str_replace( '\\', '/', $path );
+       }
 }
 
 /**