merging latest master
[lhc/web/wiklou.git] / includes / filerepo / FileRepo.php
index d4eef87..1563a58 100644 (file)
@@ -164,18 +164,6 @@ class FileRepo {
                return $status;
        }
 
-       /**
-        * Take all available measures to prevent web accessibility of new deleted
-        * directories, in case the user has not configured offline storage
-        *
-        * @param $dir string
-        * @return void
-        */
-       protected function initDeletedDir( $dir ) {
-               $this->backend->secure( // prevent web access & dir listings
-                       array( 'dir' => $dir, 'noAccess' => true, 'noListing' => true ) );
-       }
-
        /**
         * Determine if a string is an mwrepo:// URL
         *
@@ -228,6 +216,28 @@ class FileRepo {
                }
        }
 
+       /**
+        * Get the thumb zone URL configured to be handled by scripts like thumb_handler.php.
+        * This is probably only useful for internal requests, such as from a fast frontend server
+        * to a slower backend server.
+        *
+        * Large sites may use a different host name for uploads than for wikis. In any case, the
+        * wiki configuration is needed in order to use thumb.php. To avoid extracting the wiki ID
+        * from the URL path, one can configure thumb_handler.php to recognize a special path on the
+        * same host name as the wiki that is used for viewing thumbnails.
+        *
+        * @param $zone String: one of: public, deleted, temp, thumb
+        * @return String or false
+        */
+       public function getZoneHandlerUrl( $zone ) {
+               if ( isset( $this->zones[$zone]['handlerUrl'] )
+                       && in_array( $zone, array( 'public', 'temp', 'thumb' ) ) )
+               {
+                       return $this->zones[$zone]['handlerUrl'];
+               }
+               return false;
+       }
+
        /**
         * Get the backend storage path corresponding to a virtual URL.
         * Use this function wisely.
@@ -451,6 +461,24 @@ class FileRepo {
                return array();
        }
 
+       /**
+        * Get an array of arrays or iterators of file objects for files that
+        * have the given SHA-1 content hashes.
+        *
+        * @param $hashes array An array of hashes
+        * @return array An Array of arrays or iterators of file objects and the hash as key
+        */
+       public function findBySha1s( array $hashes ) {
+               $result = array();
+               foreach ( $hashes as $hash ) {
+                       $files = $this->findBySha1( $hash );
+                       if ( count( $files ) ) {
+                               $result[$hash] = $files;
+                       }
+               }
+               return $result;
+       }
+
        /**
         * Get the public root URL of the repository
         *
@@ -726,14 +754,10 @@ class FileRepo {
                        $dstPath = "$root/$dstRel";
                        $dstDir  = dirname( $dstPath );
                        // Create destination directories for this triplet
-                       if ( !$backend->prepare( array( 'dir' => $dstDir ) )->isOK() ) {
+                       if ( !$this->initDirectory( $dstDir )->isOK() ) {
                                return $this->newFatal( 'directorycreateerror', $dstDir );
                        }
 
-                       if ( $dstZone == 'deleted' ) {
-                               $this->initDeletedDir( $dstDir );
-                       }
-
                        // Resolve source to a storage path if virtual
                        $srcPath = $this->resolveToStoragePath( $srcPath );
 
@@ -863,12 +887,13 @@ class FileRepo {
                $operations = array();
                foreach ( $pairs as $pair ) {
                        list ( $src, $dst ) = $pair;
+                       $dst = $this->resolveToStoragePath( $dst );
                        $operations[] = array(
                                'op'        => 'store',
                                'src'       => $src,
-                               'dst'       => $this->resolveToStoragePath( $dst )
+                               'dst'       => $dst
                        );
-                       $this->backend->prepare( array( 'dir' => dirname( $dst ) ) );
+                       $status->merge( $this->initDirectory( dirname( $dst ) ) );
                }
                $status->merge( $this->backend->doQuickOperations( $operations ) );
 
@@ -1058,10 +1083,10 @@ class FileRepo {
                        $dstDir = dirname( $dstPath );
                        $archiveDir = dirname( $archivePath );
                        // Abort immediately on directory creation errors since they're likely to be repetitive
-                       if ( !$backend->prepare( array( 'dir' => $dstDir ) )->isOK() ) {
+                       if ( !$this->initDirectory( $dstDir )->isOK() ) {
                                return $this->newFatal( 'directorycreateerror', $dstDir );
                        }
-                       if ( !$backend->prepare( array( 'dir' => $archiveDir ) )->isOK() ) {
+                       if ( !$this->initDirectory($archiveDir )->isOK() ) {
                                return $this->newFatal( 'directorycreateerror', $archiveDir );
                        }
 
@@ -1126,6 +1151,27 @@ class FileRepo {
                return $status;
        }
 
+       /**
+        * Creates a directory with the appropriate zone permissions.
+        * Callers are responsible for doing read-only and "writable repo" checks.
+        *
+        * @param $dir string Virtual URL (or storage path) of directory to clean
+        * @return Status
+        */
+       protected function initDirectory( $dir ) {
+               $path = $this->resolveToStoragePath( $dir );
+               list( $b, $container, $r ) = FileBackend::splitStoragePath( $path );
+
+               $params = array( 'dir' => $path );
+               if ( $container === $this->zones['deleted']['container'] ) {
+                       # Take all available measures to prevent web accessibility of new deleted
+                       # directories, in case the user has not configured offline storage
+                       $params = array( 'noAccess' => true, 'noListing' => true ) + $params;
+               }
+
+               return $this->backend->prepare( $params );
+       }
+
        /**
         * Deletes a directory if empty.
         *
@@ -1231,10 +1277,9 @@ class FileRepo {
                        $archiveDir = dirname( $archivePath ); // does not touch FS
 
                        // Create destination directories
-                       if ( !$backend->prepare( array( 'dir' => $archiveDir ) )->isOK() ) {
+                       if ( !$this->initDirectory( $archiveDir )->isOK() ) {
                                return $this->newFatal( 'directorycreateerror', $archiveDir );
                        }
-                       $this->initDeletedDir( $archiveDir );
 
                        $operations[] = array(
                                'op'            => 'move',
@@ -1343,18 +1388,14 @@ class FileRepo {
        }
 
        /**
-        * Get the sha1 of a file with a given virtual URL/storage path
+        * Get the sha1 (base 36) of a file with a given virtual URL/storage path
         *
         * @param $virtualUrl string
         * @return string|bool
         */
        public function getFileSha1( $virtualUrl ) {
                $path = $this->resolveToStoragePath( $virtualUrl );
-               $tmpFile = $this->backend->getLocalReference( array( 'src' => $path ) );
-               if ( !$tmpFile ) {
-                       return false;
-               }
-               return $tmpFile->getSha1Base36();
+               return $this->backend->getFileSha1Base36( array( 'src' => $path ) );
        }
 
        /**