From: Aaron Date: Thu, 6 Sep 2012 17:15:10 +0000 (-0700) Subject: [FileBackend] Work-around low header value limits in Swift. X-Git-Tag: 1.31.0-rc.0~22450^2 X-Git-Url: http://git.cyclocoop.org/%24href?a=commitdiff_plain;h=da05f24bf2892b65bcfd519f72725fbe856939d6;p=lhc%2Fweb%2Fwiklou.git [FileBackend] Work-around low header value limits in Swift. * Also added sanity check to makeContentDisposition() and made the file name optional Change-Id: Ie4bfef743d11227631606498f026e693dd8d21f3 --- diff --git a/includes/filebackend/FileBackend.php b/includes/filebackend/FileBackend.php index e59a13b46d..6b2598237c 100644 --- a/includes/filebackend/FileBackend.php +++ b/includes/filebackend/FileBackend.php @@ -1105,17 +1105,27 @@ abstract class FileBackend { } /** - * Build a Content-Disposition header value per RFC 6266 + * 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 ) { + final public static function makeContentDisposition( $type, $filename = '' ) { + $parts = array(); + $type = strtolower( $type ); - $type = in_array( $type, array( 'inline', 'attachment' ) ) ? $type : 'inline'; - return "$type; filename*=UTF-8''" . rawurlencode( basename( $filename ) ); + 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 ); } /** diff --git a/includes/filebackend/SwiftFileBackend.php b/includes/filebackend/SwiftFileBackend.php index 7f91ae39ea..ab8610730d 100644 --- a/includes/filebackend/SwiftFileBackend.php +++ b/includes/filebackend/SwiftFileBackend.php @@ -162,6 +162,24 @@ class SwiftFileBackend extends FileBackendStore { return false; } + /** + * @param $disposition string Content-Disposition header value + * @return string Truncated Content-Disposition header value to meet Swift limits + */ + protected function truncDisp( $disposition ) { + $res = ''; + foreach ( explode( ';', $disposition ) as $part ) { + $part = trim( $part ); + $new = ( $res === '' ) ? $part : "{$res};{$part}"; + if ( strlen( $new ) <= 255 ) { + $res = $new; + } else { + break; // too long; sigh + } + } + return $res; + } + /** * @see FileBackendStore::doCreateInternal() * @return Status @@ -212,7 +230,7 @@ class SwiftFileBackend extends FileBackendStore { } // Set the Content-Disposition header if requested if ( isset( $params['disposition'] ) ) { - $obj->headers['Content-Disposition'] = $params['disposition']; + $obj->headers['Content-Disposition'] = $this->truncDisp( $params['disposition'] ); } if ( !empty( $params['async'] ) ) { // deferred $op = $obj->write_async( $params['content'] ); @@ -302,7 +320,7 @@ class SwiftFileBackend extends FileBackendStore { } // Set the Content-Disposition header if requested if ( isset( $params['disposition'] ) ) { - $obj->headers['Content-Disposition'] = $params['disposition']; + $obj->headers['Content-Disposition'] = $this->truncDisp( $params['disposition'] ); } if ( !empty( $params['async'] ) ) { // deferred wfSuppressWarnings(); @@ -392,7 +410,7 @@ class SwiftFileBackend extends FileBackendStore { $dstObj = new CF_Object( $dContObj, $dstRel, false, false ); // skip HEAD $hdrs = array(); // source file headers to override with new values if ( isset( $params['disposition'] ) ) { - $hdrs['Content-Disposition'] = $params['disposition']; + $hdrs['Content-Disposition'] = $this->truncDisp( $params['disposition'] ); } if ( !empty( $params['async'] ) ) { // deferred $op = $sContObj->copy_object_to_async( $srcRel, $dContObj, $dstRel, null, $hdrs ); @@ -471,7 +489,7 @@ class SwiftFileBackend extends FileBackendStore { $dstObj = new CF_Object( $dContObj, $dstRel, false, false ); // skip HEAD $hdrs = array(); // source file headers to override with new values if ( isset( $params['disposition'] ) ) { - $hdrs['Content-Disposition'] = $params['disposition']; + $hdrs['Content-Disposition'] = $this->truncDisp( $params['disposition'] ); } if ( !empty( $params['async'] ) ) { // deferred $op = $sContObj->move_object_to_async( $srcRel, $dContObj, $dstRel, null, $hdrs );