From 409b5108896edda9adf916cd566dbce2d2b00351 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Tue, 10 Dec 2013 12:05:39 +0100 Subject: Moved content disposition code+workarounds to OCP\Response Added new OC\Response API called setContentDispositionHeader() that contains the needed workarounds for UTF8 and IE. Refactored download code to use the new API. Removed unused trashbin download file. --- lib/private/files.php | 7 +------ lib/private/response.php | 14 ++++++++++++++ lib/public/response.php | 9 +++++++++ 3 files changed, 24 insertions(+), 6 deletions(-) (limited to 'lib') diff --git a/lib/private/files.php b/lib/private/files.php index 6ffa14c0d91..e6c81d58bd2 100644 --- a/lib/private/files.php +++ b/lib/private/files.php @@ -115,12 +115,7 @@ class OC_Files { } OC_Util::obEnd(); if ($zip or \OC\Files\Filesystem::isReadable($filename)) { - if ( preg_match( "/MSIE/", $_SERVER["HTTP_USER_AGENT"] ) ) { - header( 'Content-Disposition: attachment; filename="' . rawurlencode($name) . '"' ); - } else { - header( 'Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode($name) - . '; filename="' . rawurlencode($name) . '"' ); - } + OC_Response::setContentDispositionHeader($name, 'attachment'); header('Content-Transfer-Encoding: binary'); OC_Response::disableCaching(); if ($zip) { diff --git a/lib/private/response.php b/lib/private/response.php index 674176d078b..1b9cb473d67 100644 --- a/lib/private/response.php +++ b/lib/private/response.php @@ -147,6 +147,20 @@ class OC_Response { header('Last-Modified: '.$lastModified); } + /** + * Sets the content disposition header (with possible workarounds) + * @param string $filename file name + * @param string $type disposition type, either 'attachment' or 'inline' + */ + static public function setContentDispositionHeader( $filename, $type = 'attachment' ) { + if ( preg_match( "/MSIE/", $_SERVER["HTTP_USER_AGENT"] ) ) { + header( 'Content-Disposition: ' . rawurlencode($type) . '; filename="' . rawurlencode( $filename ) . '"' ); + } else { + header( 'Content-Disposition: ' . rawurlencode($type) . '; filename*=UTF-8\'\'' . rawurlencode( $filename ) + . '; filename="' . rawurlencode( $filename ) . '"' ); + } + } + /** * @brief Send file as response, checking and setting caching headers * @param $filepath of file to send diff --git a/lib/public/response.php b/lib/public/response.php index 2ca0a0c9fa4..24d3c81d628 100644 --- a/lib/public/response.php +++ b/lib/public/response.php @@ -54,6 +54,15 @@ class Response { \OC_Response::setLastModifiedHeader( $lastModified ); } + /** + * Sets the content disposition header (with possible workarounds) + * @param string $filename file name + * @param string $type disposition type, either 'attachment' or 'inline' + */ + static public function setContentDispositionHeader( $filename, $type = 'attachment' ) { + \OC_Response::setContentDispositionHeader( $filename, $type ); + } + /** * Disable browser caching * @see enableCaching with cache_time = 0 -- cgit v1.2.3 From 82bf1f9c8ccbfed39790d22b2fbea2c5286122dc Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Tue, 10 Dec 2013 12:40:59 +0100 Subject: Added workaround for Android content disposition Fixes #5807 --- lib/private/response.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/private/response.php b/lib/private/response.php index 1b9cb473d67..c6edda0f949 100644 --- a/lib/private/response.php +++ b/lib/private/response.php @@ -153,7 +153,8 @@ class OC_Response { * @param string $type disposition type, either 'attachment' or 'inline' */ static public function setContentDispositionHeader( $filename, $type = 'attachment' ) { - if ( preg_match( "/MSIE/", $_SERVER["HTTP_USER_AGENT"] ) ) { + // Android Chrome user agent: https://developers.google.com/chrome/mobile/docs/user-agent + if ( preg_match( '/MSIE/', $_SERVER['HTTP_USER_AGENT'] ) or preg_match( '#Android.*Chrome/[.0-9]*#', $_SERVER['HTTP_USER_AGENT'] ) ) { header( 'Content-Disposition: ' . rawurlencode($type) . '; filename="' . rawurlencode( $filename ) . '"' ); } else { header( 'Content-Disposition: ' . rawurlencode($type) . '; filename*=UTF-8\'\'' . rawurlencode( $filename ) -- cgit v1.2.3 From 09bd5bd517fee80e8b44b7645b51a8ba482a4d7c Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Thu, 12 Dec 2013 11:32:56 +0100 Subject: Added isUserAgent() method to request - added isUserAgent() method to OC_Request which makes it possible to test it - OC_Response::setContentDisposition now uses OC_Request::isUserAgent() --- lib/private/request.php | 23 ++++++++++++++++++++++ lib/private/response.php | 3 +-- tests/lib/request.php | 50 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/private/request.php b/lib/private/request.php index b2afda35922..d9d5ae08e28 100755 --- a/lib/private/request.php +++ b/lib/private/request.php @@ -7,6 +7,11 @@ */ class OC_Request { + + const USER_AGENT_IE = '/MSIE/'; + // Android Chrome user agent: https://developers.google.com/chrome/mobile/docs/user-agent + const USER_AGENT_ANDROID_MOBILE_CHROME = '#Android.*Chrome/[.0-9]*#'; + /** * @brief Check overwrite condition * @param string $type @@ -210,4 +215,22 @@ class OC_Request { return false; } } + + /** + * Checks whether the user agent matches a given regex + * @param string|array $agent agent name or array of agent names + * @return boolean true if at least one of the given agent matches, + * false otherwise + */ + static public function isUserAgent($agent) { + if (!is_array($agent)) { + $agent = array($agent); + } + foreach ($agent as $regex) { + if (preg_match($regex, $_SERVER['HTTP_USER_AGENT'])) { + return true; + } + } + return false; + } } diff --git a/lib/private/response.php b/lib/private/response.php index c6edda0f949..04746437347 100644 --- a/lib/private/response.php +++ b/lib/private/response.php @@ -153,8 +153,7 @@ class OC_Response { * @param string $type disposition type, either 'attachment' or 'inline' */ static public function setContentDispositionHeader( $filename, $type = 'attachment' ) { - // Android Chrome user agent: https://developers.google.com/chrome/mobile/docs/user-agent - if ( preg_match( '/MSIE/', $_SERVER['HTTP_USER_AGENT'] ) or preg_match( '#Android.*Chrome/[.0-9]*#', $_SERVER['HTTP_USER_AGENT'] ) ) { + if (OC_Request::isUserAgent(array(OC_Request::USER_AGENT_IE, OC_Request::USER_AGENT_ANDROID_MOBILE_CHROME))) { header( 'Content-Disposition: ' . rawurlencode($type) . '; filename="' . rawurlencode( $filename ) . '"' ); } else { header( 'Content-Disposition: ' . rawurlencode($type) . '; filename*=UTF-8\'\'' . rawurlencode( $filename ) diff --git a/tests/lib/request.php b/tests/lib/request.php index 090cebc9231..c6401a57144 100644 --- a/tests/lib/request.php +++ b/tests/lib/request.php @@ -70,4 +70,54 @@ class Test_Request extends PHPUnit_Framework_TestCase { array('/oc/core1', '/oc/core/index.php'), ); } + + /** + * @dataProvider userAgentProvider + */ + public function testUserAgent($testAgent, $userAgent, $matches) { + $_SERVER['HTTP_USER_AGENT'] = $testAgent; + $this->assertEquals($matches, OC_Request::isUserAgent($userAgent)); + } + + function userAgentProvider() { + return array( + array( + 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)', + OC_Request::USER_AGENT_IE, + true + ), + array( + 'Mozilla/5.0 (X11; Linux i686; rv:24.0) Gecko/20100101 Firefox/24.0', + OC_Request::USER_AGENT_IE, + false + ), + array( + 'Mozilla/5.0 (Linux; Android 4.4; Nexus 4 Build/KRT16S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Mobile Safari/537.36', + OC_Request::USER_AGENT_ANDROID_MOBILE_CHROME, + true + ), + array( + 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)', + OC_Request::USER_AGENT_ANDROID_MOBILE_CHROME, + false + ), + // test two values + array( + 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)', + array( + OC_Request::USER_AGENT_IE, + OC_Request::USER_AGENT_ANDROID_MOBILE_CHROME, + ), + true + ), + array( + 'Mozilla/5.0 (Linux; Android 4.4; Nexus 4 Build/KRT16S) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Mobile Safari/537.36', + array( + OC_Request::USER_AGENT_IE, + OC_Request::USER_AGENT_ANDROID_MOBILE_CHROME, + ), + true + ), + ); + } } -- cgit v1.2.3