* 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
* 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
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
*
* 'dst' => <storage path>,
* 'content' => <string of new file contents>,
* 'overwrite' => <boolean>,
- * 'overwriteSame' => <boolean>
+ * 'overwriteSame' => <boolean>,
+ * 'disposition' => <Content-Disposition header value>
* );
* @endcode
*
* 'src' => <file system path>,
* 'dst' => <storage path>,
* 'overwrite' => <boolean>,
- * 'overwriteSame' => <boolean>
+ * 'overwriteSame' => <boolean>,
+ * 'disposition' => <Content-Disposition header value>
* )
* @endcode
*
* 'src' => <storage path>,
* 'dst' => <storage path>,
* 'overwrite' => <boolean>,
- * 'overwriteSame' => <boolean>
+ * 'overwriteSame' => <boolean>,
+ * 'disposition' => <Content-Disposition header value>
* )
* @endcode
*
* 'src' => <storage path>,
* 'dst' => <storage path>,
* 'overwrite' => <boolean>,
- * 'overwriteSame' => <boolean>
+ * 'overwriteSame' => <boolean>,
+ * 'disposition' => <Content-Disposition header value>
* )
* @endcode
*
* - 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.
* - 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
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 );
}
* 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
* 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
* array(
* 'op' => 'copy',
* 'src' => <storage path>,
- * 'dst' => <storage path>
+ * 'dst' => <storage path>,
+ * 'disposition' => <Content-Disposition header value>
* )
* @endcode
* d) Move a file within storage
* array(
* 'op' => 'move',
* 'src' => <storage path>,
- * 'dst' => <storage path>
+ * 'dst' => <storage path>,
+ * 'disposition' => <Content-Disposition header value>
* )
* @endcode
* e) Delete a file within storage
* @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)
/**
* 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:
/**
* 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
*/
/**
* 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.
*
/**
* 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.
*
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.