Skip to content

Commit 17ba72b

Browse files
committed
Fix download over SSL using IE < 8 and binary file response
1 parent 7e77eb6 commit 17ba72b

File tree

5 files changed

+108
-80
lines changed

5 files changed

+108
-80
lines changed

BinaryFileResponse.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ public function prepare(Request $request)
166166
$this->setProtocolVersion('1.1');
167167
}
168168

169+
$this->ensureIEOverSSLCompatibility($request);
170+
169171
$this->offset = 0;
170172
$this->maxlen = -1;
171173

Response.php

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -253,15 +253,7 @@ public function prepare(Request $request)
253253
$this->headers->set('expires', -1);
254254
}
255255

256-
/**
257-
* Check if we need to remove Cache-Control for ssl encrypted downloads when using IE < 9
258-
* @link http://support.microsoft.com/kb/323308
259-
*/
260-
if (false !== stripos($this->headers->get('Content-Disposition'), 'attachment') && preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT'), $match) == 1 && true === $request->isSecure()) {
261-
if (intval(preg_replace("/(MSIE )(.*?);/", "$2", $match[0])) < 9) {
262-
$this->headers->remove('Cache-Control');
263-
}
264-
}
256+
$this->ensureIEOverSSLCompatibility($request);
265257

266258
return $this;
267259
}
@@ -1179,4 +1171,18 @@ public function isEmpty()
11791171
{
11801172
return in_array($this->statusCode, array(201, 204, 304));
11811173
}
1174+
1175+
/**
1176+
* Check if we need to remove Cache-Control for ssl encrypted downloads when using IE < 9
1177+
*
1178+
* @link http://support.microsoft.com/kb/323308
1179+
*/
1180+
protected function ensureIEOverSSLCompatibility(Request $request)
1181+
{
1182+
if (false !== stripos($this->headers->get('Content-Disposition'), 'attachment') && preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT'), $match) == 1 && true === $request->isSecure()) {
1183+
if (intval(preg_replace("/(MSIE )(.*?);/", "$2", $match[0])) < 9) {
1184+
$this->headers->remove('Cache-Control');
1185+
}
1186+
}
1187+
}
11821188
}

Tests/BinaryFileResponseTest.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
use Symfony\Component\HttpFoundation\Request;
1616
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
1717

18-
class BinaryFileResponseTest extends \PHPUnit_Framework_TestCase
18+
class BinaryFileResponseTest extends ResponseTestCase
1919
{
2020
public function testConstruction()
2121
{
@@ -145,4 +145,9 @@ public function getSampleXAccelMappings()
145145
array('/home/foo/bar.txt', '/files/=/var/www/,/baz/=/home/foo/', '/baz/bar.txt'),
146146
);
147147
}
148+
149+
protected function provideResponse()
150+
{
151+
return new BinaryFileResponse('README.md');
152+
}
148153
}

Tests/ResponseTest.php

Lines changed: 6 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
use Symfony\Component\HttpFoundation\Request;
1515
use Symfony\Component\HttpFoundation\Response;
1616

17-
class ResponseTest extends \PHPUnit_Framework_TestCase
17+
class ResponseTest extends ResponseTestCase
1818
{
1919
public function testCreate()
2020
{
@@ -326,75 +326,6 @@ public function testContentTypeCharset()
326326
$this->assertEquals('text/css; charset=UTF-8', $response->headers->get('Content-Type'));
327327
}
328328

329-
public function testNoCacheControlHeaderOnAttachmentUsingHTTPSAndMSIE()
330-
{
331-
// Check for HTTPS and IE 8
332-
$request = new Request();
333-
$request->server->set('HTTPS', true);
334-
$request->server->set('HTTP_USER_AGENT', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)');
335-
336-
$response = new Response();
337-
$response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
338-
$response->prepare($request);
339-
340-
$this->assertFalse($response->headers->has('Cache-Control'));
341-
342-
// Check for IE 10 and HTTPS
343-
$request->server->set('HTTP_USER_AGENT', 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)');
344-
345-
$response = new Response();
346-
$response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
347-
$response->prepare($request);
348-
349-
$this->assertTrue($response->headers->has('Cache-Control'));
350-
351-
// Check for IE 9 and HTTPS
352-
$request->server->set('HTTP_USER_AGENT', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 7.1; Trident/5.0)');
353-
354-
$response = new Response();
355-
$response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
356-
$response->prepare($request);
357-
358-
$this->assertTrue($response->headers->has('Cache-Control'));
359-
360-
// Check for IE 9 and HTTP
361-
$request->server->set('HTTPS', false);
362-
363-
$response = new Response();
364-
$response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
365-
$response->prepare($request);
366-
367-
$this->assertTrue($response->headers->has('Cache-Control'));
368-
369-
// Check for IE 8 and HTTP
370-
$request->server->set('HTTP_USER_AGENT', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)');
371-
372-
$response = new Response();
373-
$response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
374-
$response->prepare($request);
375-
376-
$this->assertTrue($response->headers->has('Cache-Control'));
377-
378-
// Check for non-IE and HTTPS
379-
$request->server->set('HTTPS', true);
380-
$request->server->set('HTTP_USER_AGENT', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.60 Safari/537.17');
381-
382-
$response = new Response();
383-
$response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
384-
$response->prepare($request);
385-
386-
$this->assertTrue($response->headers->has('Cache-Control'));
387-
388-
// Check for non-IE and HTTP
389-
$request->server->set('HTTPS', false);
390-
391-
$response = new Response();
392-
$response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
393-
$response->prepare($request);
394-
395-
$this->assertTrue($response->headers->has('Cache-Control'));
396-
}
397-
398329
public function testPrepareDoesNothingIfContentTypeIsSet()
399330
{
400331
$response = new Response('foo');
@@ -770,6 +701,11 @@ protected function createDateTimeNow()
770701
{
771702
return new \DateTime();
772703
}
704+
705+
protected function provideResponse()
706+
{
707+
return new Response();
708+
}
773709
}
774710

775711
class StringableObject

Tests/ResponseTestCase.php

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
namespace Symfony\Component\HttpFoundation\Tests;
4+
5+
use Symfony\Component\HttpFoundation\Request;
6+
7+
abstract class ResponseTestCase extends \PHPUnit_Framework_TestCase
8+
{
9+
public function testNoCacheControlHeaderOnAttachmentUsingHTTPSAndMSIE()
10+
{
11+
// Check for HTTPS and IE 8
12+
$request = new Request();
13+
$request->server->set('HTTPS', true);
14+
$request->server->set('HTTP_USER_AGENT', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)');
15+
16+
$response = $this->provideResponse();
17+
$response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
18+
$response->prepare($request);
19+
20+
$this->assertFalse($response->headers->has('Cache-Control'));
21+
22+
// Check for IE 10 and HTTPS
23+
$request->server->set('HTTP_USER_AGENT', 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)');
24+
25+
$response = $this->provideResponse();
26+
$response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
27+
$response->prepare($request);
28+
29+
$this->assertTrue($response->headers->has('Cache-Control'));
30+
31+
// Check for IE 9 and HTTPS
32+
$request->server->set('HTTP_USER_AGENT', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 7.1; Trident/5.0)');
33+
34+
$response = $this->provideResponse();
35+
$response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
36+
$response->prepare($request);
37+
38+
$this->assertTrue($response->headers->has('Cache-Control'));
39+
40+
// Check for IE 9 and HTTP
41+
$request->server->set('HTTPS', false);
42+
43+
$response = $this->provideResponse();
44+
$response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
45+
$response->prepare($request);
46+
47+
$this->assertTrue($response->headers->has('Cache-Control'));
48+
49+
// Check for IE 8 and HTTP
50+
$request->server->set('HTTP_USER_AGENT', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)');
51+
52+
$response = $this->provideResponse();
53+
$response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
54+
$response->prepare($request);
55+
56+
$this->assertTrue($response->headers->has('Cache-Control'));
57+
58+
// Check for non-IE and HTTPS
59+
$request->server->set('HTTPS', true);
60+
$request->server->set('HTTP_USER_AGENT', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.60 Safari/537.17');
61+
62+
$response = $this->provideResponse();
63+
$response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
64+
$response->prepare($request);
65+
66+
$this->assertTrue($response->headers->has('Cache-Control'));
67+
68+
// Check for non-IE and HTTP
69+
$request->server->set('HTTPS', false);
70+
71+
$response = $this->provideResponse();
72+
$response->headers->set('Content-Disposition', 'attachment; filename="fname.ext"');
73+
$response->prepare($request);
74+
75+
$this->assertTrue($response->headers->has('Cache-Control'));
76+
}
77+
78+
abstract protected function provideResponse();
79+
}

0 commit comments

Comments
 (0)