c5189fac206a068410b4ea2795102e8073b9161b
[yaffs-website] / web / core / modules / file / src / Tests / DownloadTest.php
1 <?php
2
3 namespace Drupal\file\Tests;
4
5 /**
6  * Tests for download/file transfer functions.
7  *
8  * @group file
9  */
10 class DownloadTest extends FileManagedTestBase {
11   protected function setUp() {
12     parent::setUp();
13     // Clear out any hook calls.
14     file_test_reset();
15   }
16
17   /**
18    * Test the public file transfer system.
19    */
20   public function testPublicFileTransfer() {
21     // Test generating a URL to a created file.
22     $file = $this->createFile();
23     $url = file_create_url($file->getFileUri());
24     // URLs can't contain characters outside the ASCII set so $filename has to be
25     // encoded.
26     $filename = $GLOBALS['base_url'] . '/' . \Drupal::service('stream_wrapper_manager')->getViaScheme('public')->getDirectoryPath() . '/' . rawurlencode($file->getFilename());
27     $this->assertEqual($filename, $url, 'Correctly generated a URL for a created file.');
28     $this->drupalHead($url);
29     $this->assertResponse(200, 'Confirmed that the generated URL is correct by downloading the created file.');
30
31     // Test generating a URL to a shipped file (i.e. a file that is part of
32     // Drupal core, a module or a theme, for example a JavaScript file).
33     $filepath = 'core/assets/vendor/jquery/jquery.min.js';
34     $url = file_create_url($filepath);
35     $this->assertEqual($GLOBALS['base_url'] . '/' . $filepath, $url, 'Correctly generated a URL for a shipped file.');
36     $this->drupalHead($url);
37     $this->assertResponse(200, 'Confirmed that the generated URL is correct by downloading the shipped file.');
38   }
39
40   /**
41    * Test the private file transfer system.
42    */
43   public function testPrivateFileTransferWithoutPageCache() {
44     $this->doPrivateFileTransferTest();
45   }
46
47   /**
48    * Test the private file transfer system.
49    */
50   protected function doPrivateFileTransferTest() {
51     // Set file downloads to private so handler functions get called.
52
53     // Create a file.
54     $contents = $this->randomMachineName(8);
55     $file = $this->createFile(NULL, $contents, 'private');
56     // Created private files without usage are by default not accessible
57     // for a user different from the owner, but createFile always uses uid 1
58     // as the owner of the files. Therefore make it permanent to allow access
59     // if a module allows it.
60     $file->setPermanent();
61     $file->save();
62
63     $url  = file_create_url($file->getFileUri());
64
65     // Set file_test access header to allow the download.
66     file_test_set_return('download', ['x-foo' => 'Bar']);
67     $this->drupalGet($url);
68     $this->assertEqual($this->drupalGetHeader('x-foo'), 'Bar', 'Found header set by file_test module on private download.');
69     $this->assertFalse($this->drupalGetHeader('x-drupal-cache'), 'Page cache is disabled on private file download.');
70     $this->assertResponse(200, 'Correctly allowed access to a file when file_test provides headers.');
71
72     // Test that the file transferred correctly.
73     $this->assertEqual($contents, $this->content, 'Contents of the file are correct.');
74
75     // Deny access to all downloads via a -1 header.
76     file_test_set_return('download', -1);
77     $this->drupalHead($url);
78     $this->assertResponse(403, 'Correctly denied access to a file when file_test sets the header to -1.');
79
80     // Try non-existent file.
81     $url = file_create_url('private://' . $this->randomMachineName());
82     $this->drupalHead($url);
83     $this->assertResponse(404, 'Correctly returned 404 response for a non-existent file.');
84   }
85
86   /**
87    * Test file_create_url().
88    */
89   public function testFileCreateUrl() {
90
91     // Tilde (~) is excluded from this test because it is encoded by
92     // rawurlencode() in PHP 5.2 but not in PHP 5.3, as per RFC 3986.
93     // @see http://php.net/manual/function.rawurlencode.php#86506
94     $basename = " -._!$'\"()*@[]?&+%#,;=:\n\x00" . // "Special" ASCII characters.
95       "%23%25%26%2B%2F%3F" . // Characters that look like a percent-escaped string.
96       "éøïвβ中國書۞"; // Characters from various non-ASCII alphabets.
97     $basename_encoded = '%20-._%21%24%27%22%28%29%2A%40%5B%5D%3F%26%2B%25%23%2C%3B%3D%3A__' .
98       '%2523%2525%2526%252B%252F%253F' .
99       '%C3%A9%C3%B8%C3%AF%D0%B2%CE%B2%E4%B8%AD%E5%9C%8B%E6%9B%B8%DB%9E';
100
101     // Public files should not be served by Drupal, so their URLs should not be
102     // routed through Drupal, whereas private files should be served by Drupal,
103     // so they need to be. The difference is most apparent when $script_path
104     // is not empty (i.e., when not using clean URLs).
105     $clean_url_settings = [
106       'clean' => '',
107       'unclean' => 'index.php/',
108     ];
109     $public_directory_path = \Drupal::service('stream_wrapper_manager')->getViaScheme('public')->getDirectoryPath();
110     foreach ($clean_url_settings as $clean_url_setting => $script_path) {
111       $clean_urls = $clean_url_setting == 'clean';
112       $request = $this->prepareRequestForGenerator($clean_urls);
113       $base_path = $request->getSchemeAndHttpHost() . $request->getBasePath();
114       $this->checkUrl('public', '', $basename, $base_path . '/' . $public_directory_path . '/' . $basename_encoded);
115       $this->checkUrl('private', '', $basename, $base_path . '/' . $script_path . 'system/files/' . $basename_encoded);
116     }
117     $this->assertEqual(file_create_url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='), 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==', t('Generated URL matches expected URL.'));
118     // Test public files with a different host name from settings.
119     $test_base_url = 'http://www.example.com/cdn';
120     $this->settingsSet('file_public_base_url', $test_base_url);
121     $filepath = file_create_filename('test.txt', '');
122     $directory_uri = 'public://' . dirname($filepath);
123     file_prepare_directory($directory_uri, FILE_CREATE_DIRECTORY);
124     $file = $this->createFile($filepath, NULL, 'public');
125     $url = file_create_url($file->getFileUri());
126     $expected_url = $test_base_url . '/' . basename($filepath);
127     $this->assertEqual($url, $expected_url);
128   }
129
130   /**
131    * Download a file from the URL generated by file_create_url().
132    *
133    * Create a file with the specified scheme, directory and filename; check that
134    * the URL generated by file_create_url() for the specified file equals the
135    * specified URL; fetch the URL and then compare the contents to the file.
136    *
137    * @param string $scheme
138    *   A scheme, e.g. "public".
139    * @param string $directory
140    *   A directory, possibly "".
141    * @param string $filename
142    *   A filename.
143    * @param string $expected_url
144    *   The expected URL.
145    */
146   private function checkUrl($scheme, $directory, $filename, $expected_url) {
147     // Convert $filename to a valid filename, i.e. strip characters not
148     // supported by the filesystem, and create the file in the specified
149     // directory.
150     $filepath = file_create_filename($filename, $directory);
151     $directory_uri = $scheme . '://' . dirname($filepath);
152     file_prepare_directory($directory_uri, FILE_CREATE_DIRECTORY);
153     $file = $this->createFile($filepath, NULL, $scheme);
154
155     $url = file_create_url($file->getFileUri());
156     $this->assertEqual($url, $expected_url);
157
158     if ($scheme == 'private') {
159       // Tell the implementation of hook_file_download() in file_test.module
160       // that this file may be downloaded.
161       file_test_set_return('download', ['x-foo' => 'Bar']);
162     }
163
164     $this->drupalGet($url);
165     if ($this->assertResponse(200) == 'pass') {
166       $this->assertRaw(file_get_contents($file->getFileUri()), 'Contents of the file are correct.');
167     }
168
169     $file->delete();
170   }
171
172 }