/**
* @see FileBackend::__construct()
* Additional $config params include:
- * - wanCache : WANOBjectCache object to use for persistent caching.
+ * - wanCache : WANObjectCache object to use for persistent caching.
* - mimeCallback : Callback that takes (storage path, content, file system path) and
* returns the MIME type of the file or 'unknown/unknown'. The file
* system path parameter should be used if the content one is null.
parent::__construct( $config );
$this->mimeCallback = isset( $config['mimeCallback'] )
? $config['mimeCallback']
- : function ( $storagePath, $content, $fsPath ) {
- // @todo handle the case of extension-less files using the contents
- return StreamFile::contentTypeFromPath( $storagePath ) ?: 'unknown/unknown';
- };
+ : null;
$this->memCache = WANObjectCache::newEmpty(); // disabled by default
$this->cheapCache = new ProcessCacheLRU( self::CACHE_CHEAP_SIZE );
$this->expensiveCache = new ProcessCacheLRU( self::CACHE_EXPENSIVE_SIZE );
$status = Status::newGood();
// Fix up custom header name/value pairs...
- $ops = array_map( array( $this, 'stripInvalidHeadersFromOp' ), $ops );
+ $ops = array_map( array( $this, 'sanitizeOpHeaders' ), $ops );
// Build up a list of FileOps...
$performOps = $this->getOperationsInternal( $ops );
$status = Status::newGood();
// Fix up custom header name/value pairs...
- $ops = array_map( array( $this, 'stripInvalidHeadersFromOp' ), $ops );
+ $ops = array_map( array( $this, 'sanitizeOpHeaders' ), $ops );
// Clear any file cache entries
$this->clearCache();
}
/**
- * Strip long HTTP headers from a file operation.
+ * Normalize and filter HTTP headers from a file operation
+ *
+ * This normalizes and strips long HTTP headers from a file operation.
* Most headers are just numbers, but some are allowed to be long.
* This function is useful for cleaning up headers and avoiding backend
* specific errors, especially in the middle of batch file operations.
* @param array $op Same format as doOperation()
* @return array
*/
- protected function stripInvalidHeadersFromOp( array $op ) {
- static $longs = array( 'Content-Disposition' );
+ protected function sanitizeOpHeaders( array $op ) {
+ static $longs = array( 'content-disposition' );
+
if ( isset( $op['headers'] ) ) { // op sets HTTP headers
+ $newHeaders = array();
foreach ( $op['headers'] as $name => $value ) {
+ $name = strtolower( $name );
$maxHVLen = in_array( $name, $longs ) ? INF : 255;
if ( strlen( $name ) > 255 || strlen( $value ) > $maxHVLen ) {
trigger_error( "Header '$name: $value' is too long." );
- unset( $op['headers'][$name] );
- } elseif ( !strlen( $value ) ) {
- $op['headers'][$name] = ''; // null/false => ""
+ } else {
+ $newHeaders[$name] = strlen( $value ) ? $value : ''; // null/false => ""
}
}
+ $op['headers'] = $newHeaders;
}
return $op;
$pathNames[$this->fileCacheKey( $path )] = $path;
}
}
- // Get all cache entries for these container cache keys...
+ // Get all cache entries for these file cache keys...
$values = $this->memCache->getMulti( array_keys( $pathNames ) );
foreach ( $values as $cacheKey => $val ) {
$path = $pathNames[$cacheKey];
* @return string MIME type
*/
protected function getContentType( $storagePath, $content, $fsPath ) {
- return call_user_func_array( $this->mimeCallback, func_get_args() );
+ if ( $this->mimeCallback ) {
+ return call_user_func_array( $this->mimeCallback, func_get_args() );
+ }
+
+ $mime = null;
+ if ( $fsPath !== null && function_exists( 'finfo_file' ) ) {
+ $finfo = finfo_open( FILEINFO_MIME_TYPE );
+ $mime = finfo_file( $finfo, $fsPath );
+ finfo_close( $finfo );
+ }
+
+ return is_string( $mime ) ? $mime : 'unknown/unknown';
}
}