Merge "Normalize header case for FileBackend operations"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Sun, 1 Nov 2015 23:28:22 +0000 (23:28 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Sun, 1 Nov 2015 23:28:22 +0000 (23:28 +0000)
includes/filebackend/FileBackendStore.php
tests/phpunit/includes/filebackend/FileBackendTest.php

index e5ce968..4ec81ec 100644 (file)
@@ -1066,7 +1066,7 @@ abstract class FileBackendStore extends FileBackend {
                $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 );
@@ -1133,7 +1133,7 @@ abstract class FileBackendStore extends FileBackend {
                $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();
@@ -1230,7 +1230,9 @@ abstract class FileBackendStore extends FileBackend {
        }
 
        /**
-        * 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.
@@ -1238,18 +1240,21 @@ abstract class FileBackendStore extends FileBackend {
         * @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;
index 0d15b75..e7d092f 100644 (file)
@@ -2495,6 +2495,37 @@ class FileBackendTest extends MediaWikiTestCase {
                );
        }
 
+       public function testSanitizeOpHeaders() {
+               $be = TestingAccessWrapper::newFromObject( new MemoryFileBackend( array(
+                       'name' => 'localtesting',
+                       'wikiId' => wfWikiID()
+               ) ) );
+
+               $name = wfRandomString( 300 );
+
+               $input = array(
+                       'headers' => array(
+                               'content-Disposition' => FileBackend::makeContentDisposition( 'inline', $name ),
+                               'Content-dUration' => 25.6,
+                               'X-LONG-VALUE' => str_pad( '0', 300 ),
+                               'CONTENT-LENGTH' => 855055,
+                       )
+               );
+               $expected = array(
+                       'headers' => array(
+                               'content-disposition' => FileBackend::makeContentDisposition( 'inline', $name ),
+                               'content-duration' => 25.6,
+                               'content-length' => 855055
+                       )
+               );
+
+               MediaWiki\suppressWarnings();
+               $actual = $be->sanitizeOpHeaders( $input );
+               MediaWiki\restoreWarnings();
+
+               $this->assertEquals( $expected, $actual, "Header sanitized properly" );
+       }
+
        // helper function
        private function listToArray( $iter ) {
                return is_array( $iter ) ? $iter : iterator_to_array( $iter );