[FileBackend] Added FileBackend::getWikiID() function.
[lhc/web/wiklou.git] / includes / filebackend / FileBackend.php
index cb2433a..306bf35 100644 (file)
@@ -39,8 +39,7 @@
  * All "storage paths" are of the format "mwstore://<backend>/<container>/<path>".
  * The "<path>" portion is a relative path that uses UNIX file system (FS)
  * notation, though any particular backend may not actually be using a local
- * filesystem.
- * Therefore, the relative paths are only virtual.
+ * filesystem. Therefore, the relative paths are only virtual.
  *
  * Backend contents are stored under wiki-specific container names by default.
  * For legacy reasons, this has no effect for the FS backend class, and per-wiki
@@ -51,7 +50,7 @@
  * backends with virtual directories may not have this limitation. Callers should
  * store files in such a way that no files and directories are under the same path.
  *
- * Methods should avoid throwing exceptions at all costs.
+ * Methods of subclasses should avoid throwing exceptions at all costs.
  * As a corollary, external dependencies should be kept to a minimum.
  *
  * @ingroup FileBackend
@@ -129,6 +128,16 @@ abstract class FileBackend {
                return $this->name;
        }
 
+       /**
+        * Get the wiki identifier used for this backend (possibly empty)
+        *
+        * @return string
+        * @since 1.20
+        */
+       final public function getWikiId() {
+               return $this->wikiId;
+       }
+
        /**
         * Check if this backend is read-only
         *
@@ -171,7 +180,8 @@ abstract class FileBackend {
         *         'dst'                 => <storage path>,
         *         'content'             => <string of new file contents>,
         *         'overwrite'           => <boolean>,
-        *         'overwriteSame'       => <boolean>
+        *         'overwriteSame'       => <boolean>,
+        *         'disposition'         => <Content-Disposition header value>
         *     );
         * @endcode
         *
@@ -182,7 +192,8 @@ abstract class FileBackend {
         *         'src'                 => <file system path>,
         *         'dst'                 => <storage path>,
         *         'overwrite'           => <boolean>,
-        *         'overwriteSame'       => <boolean>
+        *         'overwriteSame'       => <boolean>,
+        *         'disposition'         => <Content-Disposition header value>
         *     )
         * @endcode
         *
@@ -193,7 +204,8 @@ abstract class FileBackend {
         *         'src'                 => <storage path>,
         *         'dst'                 => <storage path>,
         *         'overwrite'           => <boolean>,
-        *         'overwriteSame'       => <boolean>
+        *         'overwriteSame'       => <boolean>,
+        *         'disposition'         => <Content-Disposition header value>
         *     )
         * @endcode
         *
@@ -204,7 +216,8 @@ abstract class FileBackend {
         *         'src'                 => <storage path>,
         *         'dst'                 => <storage path>,
         *         'overwrite'           => <boolean>,
-        *         'overwriteSame'       => <boolean>
+        *         'overwriteSame'       => <boolean>,
+        *         'disposition'         => <Content-Disposition header value>
         *     )
         * @endcode
         *
@@ -231,6 +244,10 @@ abstract class FileBackend {
         *   - overwriteSame       : An error will not be given if a file already
         *                           exists at the destination that has the same
         *                           contents as the new contents to be written there.
+        *   - disposition         : When supplied, the backend will add a Content-Disposition
+        *                           header when GETs/HEADs of the destination file are made.
+        *                           Backends that don't support file metadata will ignore this.
+        *                           See http://tools.ietf.org/html/rfc6266 (since 1.20).
         *
         * $opts is an associative of boolean flags, including:
         *   - force               : Operation precondition errors no longer trigger an abort.
@@ -242,13 +259,13 @@ abstract class FileBackend {
         *   - allowStale          : Don't require the latest available data.
         *                           This can increase performance for non-critical writes.
         *                           This has no effect unless the 'force' flag is set.
-        *   - preserveCache       : Don't clear the process cache before checking files.
-        *                           This should only be used if all entries in the process
-        *                           cache were added after the files were already locked.
         *   - nonJournaled        : Don't log this operation batch in the file journal.
         *                           This limits the ability of recovery scripts.
         *   - parallelize         : Try to do operations in parallel when possible.
         *   - bypassReadOnly      : Allow writes in read-only mode (since 1.20).
+        *   - preserveCache       : Don't clear the process cache before checking files.
+        *                           This should only be used if all entries in the process
+        *                           cache were added after the files were already locked (since 1.20).
         *
         * @remarks Remarks on locking:
         * File system paths given to operations should refer to files that are
@@ -277,16 +294,6 @@ abstract class FileBackend {
                        unset( $opts['nonLocking'] );
                        unset( $opts['allowStale'] );
                }
-               $opts['concurrency'] = 1; // off
-               if ( $this->parallelize === 'implicit' ) {
-                       if ( !isset( $opts['parallelize'] ) || $opts['parallelize'] ) {
-                               $opts['concurrency'] = $this->concurrency;
-                       }
-               } elseif ( $this->parallelize === 'explicit' ) {
-                       if ( !empty( $opts['parallelize'] ) ) {
-                               $opts['concurrency'] = $this->concurrency;
-                       }
-               }
                return $this->doOperationsInternal( $ops, $opts );
        }
 
@@ -400,7 +407,8 @@ abstract class FileBackend {
         *     array(
         *         'op'                  => 'create',
         *         'dst'                 => <storage path>,
-        *         'content'             => <string of new file contents>
+        *         'content'             => <string of new file contents>,
+        *         'disposition'         => <Content-Disposition header value>
         *     )
         * @endcode
         * b) Copy a file system file into storage
@@ -408,7 +416,8 @@ abstract class FileBackend {
         *     array(
         *         'op'                  => 'store',
         *         'src'                 => <file system path>,
-        *         'dst'                 => <storage path>
+        *         'dst'                 => <storage path>,
+        *         'disposition'         => <Content-Disposition header value>
         *     )
         * @endcode
         * c) Copy a file within storage
@@ -416,7 +425,8 @@ abstract class FileBackend {
         *     array(
         *         'op'                  => 'copy',
         *         'src'                 => <storage path>,
-        *         'dst'                 => <storage path>
+        *         'dst'                 => <storage path>,
+        *         'disposition'         => <Content-Disposition header value>
         *     )
         * @endcode
         * d) Move a file within storage
@@ -424,7 +434,8 @@ abstract class FileBackend {
         *     array(
         *         'op'                  => 'move',
         *         'src'                 => <storage path>,
-        *         'dst'                 => <storage path>
+        *         'dst'                 => <storage path>,
+        *         'disposition'         => <Content-Disposition header value>
         *     )
         * @endcode
         * e) Delete a file within storage
@@ -445,6 +456,10 @@ abstract class FileBackend {
         * @par Boolean flags for operations (operation-specific):
         *   - ignoreMissingSource : The operation will simply succeed and do
         *                           nothing if the source file does not exist.
+        *   - disposition         : When supplied, the backend will add a Content-Disposition
+        *                           header when GETs/HEADs of the destination file are made.
+        *                           Backends that don't support file metadata will ignore this.
+        *                           See http://tools.ietf.org/html/rfc6266 (since 1.20).
         *
         * $opts is an associative of boolean flags, including:
         *   - bypassReadOnly      : Allow writes in read-only mode (since 1.20)
@@ -661,7 +676,7 @@ abstract class FileBackend {
        /**
         * Delete a storage directory if it is empty.
         * Backends using key/value stores may do nothing unless the directory
-        * is that of an empty container, in which case it should be deleted.
+        * is that of an empty container, in which case it will be deleted.
         *
         * @param $params Array
         * $params include:
@@ -769,15 +784,15 @@ abstract class FileBackend {
 
        /**
         * Stream the file at a storage path in the backend.
-        * If the file does not exists, a 404 error will be given.
+        * If the file does not exists, an HTTP 404 error will be given.
         * Appropriate HTTP headers (Status, Content-Type, Content-Length)
-        * must be sent if streaming began, while none should be sent otherwise.
+        * will be sent if streaming began, while none will be sent otherwise.
         * Implementations should flush the output buffer before sending data.
         *
         * @param $params Array
         * $params include:
         *   - src     : source storage path
-        *   - headers : additional HTTP headers to send on success
+        *   - headers : list of additional HTTP headers to send on success
         *   - latest  : use the latest available data
         * @return Status
         */
@@ -835,10 +850,10 @@ abstract class FileBackend {
        /**
         * Get an iterator to list *all* directories under a storage directory.
         * If the directory is of the form "mwstore://backend/container",
-        * then all directories in the container should be listed.
+        * then all directories in the container will be listed.
         * If the directory is of form "mwstore://backend/container/dir",
-        * then all directories directly under that directory should be listed.
-        * Results should be storage directories relative to the given directory.
+        * then all directories directly under that directory will be listed.
+        * Results will be storage directories relative to the given directory.
         *
         * Storage backends with eventual consistency might return stale data.
         *
@@ -870,10 +885,10 @@ abstract class FileBackend {
        /**
         * Get an iterator to list *all* stored files under a storage directory.
         * If the directory is of the form "mwstore://backend/container",
-        * then all files in the container should be listed.
+        * then all files in the container will be listed.
         * If the directory is of form "mwstore://backend/container/dir",
-        * then all files under that directory should be listed.
-        * Results should be storage paths relative to the given directory.
+        * then all files under that directory will be listed.
+        * Results will be storage paths relative to the given directory.
         *
         * Storage backends with eventual consistency might return stale data.
         *
@@ -1089,6 +1104,30 @@ abstract class FileBackend {
                return ( self::normalizeContainerPath( $path ) !== null );
        }
 
+       /**
+        * Build a Content-Disposition header value per RFC 6266.
+        *
+        * @param $type string One of (attachment, inline)
+        * @param $filename string Suggested file name (should not contain slashes)
+        * @return string
+        * @since 1.20
+        */
+       final public static function makeContentDisposition( $type, $filename = '' ) {
+               $parts = array();
+
+               $type = strtolower( $type );
+               if ( !in_array( $type, array( 'inline', 'attachment' ) ) ) {
+                       throw new MWException( "Invalid Content-Disposition type '$type'." );
+               }
+               $parts[] = $type;
+
+               if ( strlen( $filename ) ) {
+                       $parts[] = "filename*=UTF-8''" . rawurlencode( basename( $filename ) );
+               }
+
+               return implode( ';', $parts );
+       }
+
        /**
         * Validate and normalize a relative storage path.
         * Null is returned if the path involves directory traversal.