aboutsummaryrefslogtreecommitdiffstats
path: root/build/integration/features/bootstrap/Download.php
blob: 7879159325ad2de3302370c5c032c465deaabe7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
<?php
/**
 * @copyright Copyright (c) 2018, Daniel Calviño Sánchez (danxuliu@gmail.com)
 *
 * @author Daniel Calviño Sánchez <danxuliu@gmail.com>
 * @author John Molakvoæ <skjnldsv@protonmail.com>
 *
 * @license GNU AGPL version 3 or any later version
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 */
use PHPUnit\Framework\Assert;

require __DIR__ . '/../../vendor/autoload.php';

trait Download {

	/** @var string **/
	private $downloadedFile;

	/** @AfterScenario **/
	public function cleanupDownloadedFile() {
		$this->downloadedFile = null;
	}

	/**
	 * @When user :user downloads zip file for entries :entries in folder :folder
	 */
	public function userDownloadsZipFileForEntriesInFolder($user, $entries, $folder) {
		$this->asAn($user);
		$this->sendingToDirectUrl('GET', "/index.php/apps/files/ajax/download.php?dir=" . $folder . "&files=[" . $entries . "]");
		$this->theHTTPStatusCodeShouldBe('200');

		$this->getDownloadedFile();
	}

	private function getDownloadedFile() {
		$this->downloadedFile = '';

		$body = $this->response->getBody();
		while (!$body->eof()) {
			$this->downloadedFile .= $body->read(8192);
		}
		$body->close();
	}

	/**
	 * @Then the downloaded zip file is a zip32 file
	 */
	public function theDownloadedZipFileIsAZip32File() {
		// assertNotContains is not used to prevent the whole file from being
		// printed in case of error.
		Assert::assertTrue(
			strpos($this->downloadedFile, "\x50\x4B\x06\x06") === false,
			"File contains the zip64 end of central dir signature"
		);
	}

	/**
	 * @Then the downloaded zip file is a zip64 file
	 */
	public function theDownloadedZipFileIsAZip64File() {
		// assertNotContains is not used to prevent the whole file from being
		// printed in case of error.
		Assert::assertTrue(
			strpos($this->downloadedFile, "\x50\x4B\x06\x06") !== false,
			"File does not contain the zip64 end of central dir signature"
		);
	}

	/**
	 * @Then the downloaded zip file contains a file named :fileName with the contents of :sourceFileName from :user data
	 */
	public function theDownloadedZipFileContainsAFileNamedWithTheContentsOfFromData($fileName, $sourceFileName, $user) {
		$fileHeaderRegExp = '/';
		$fileHeaderRegExp .= "\x50\x4B\x03\x04"; // Local file header signature
		$fileHeaderRegExp .= '.{22,22}'; // Ignore from "version needed to extract" to "uncompressed size"
		$fileHeaderRegExp .= preg_quote(pack('v', strlen($fileName)), '/'); // File name length
		$fileHeaderRegExp .= '(.{2,2})'; // Get "extra field length"
		$fileHeaderRegExp .= preg_quote($fileName, '/'); // File name
		$fileHeaderRegExp .= '/s'; // PCRE_DOTALL, so all characters (including bytes that happen to be new line characters) match

		// assertRegExp is not used to prevent the whole file from being printed
		// in case of error and to be able to get the extra field length.
		Assert::assertEquals(
			1, preg_match($fileHeaderRegExp, $this->downloadedFile, $matches),
			"Local header for file did not appear once in zip file"
		);

		$extraFieldLength = unpack('vextraFieldLength', $matches[1])['extraFieldLength'];
		$expectedFileContents = file_get_contents($this->getDataDirectory() . "/$user/files" . $sourceFileName);

		$fileHeaderAndContentRegExp = '/';
		$fileHeaderAndContentRegExp .= "\x50\x4B\x03\x04"; // Local file header signature
		$fileHeaderAndContentRegExp .= '.{22,22}'; // Ignore from "version needed to extract" to "uncompressed size"
		$fileHeaderAndContentRegExp .= preg_quote(pack('v', strlen($fileName)), '/'); // File name length
		$fileHeaderAndContentRegExp .= '.{2,2}'; // Ignore "extra field length"
		$fileHeaderAndContentRegExp .= preg_quote($fileName, '/'); // File name
		$fileHeaderAndContentRegExp .= '.{' . $extraFieldLength . ',' . $extraFieldLength . '}'; // Ignore "extra field"
		$fileHeaderAndContentRegExp .= preg_quote($expectedFileContents, '/'); // File contents
		$fileHeaderAndContentRegExp .= '/s'; // PCRE_DOTALL, so all characters (including bytes that happen to be new line characters) match

		// assertRegExp is not used to prevent the whole file from being printed
		// in case of error.
		Assert::assertEquals(
			1, preg_match($fileHeaderAndContentRegExp, $this->downloadedFile),
			"Local header and contents for file did not appear once in zip file"
		);
	}

	/**
	 * @Then the downloaded zip file contains a folder named :folderName
	 */
	public function theDownloadedZipFileContainsAFolderNamed($folderName) {
		$folderHeaderRegExp = '/';
		$folderHeaderRegExp .= "\x50\x4B\x03\x04"; // Local file header signature
		$folderHeaderRegExp .= '.{22,22}'; // Ignore from "version needed to extract" to "uncompressed size"
		$folderHeaderRegExp .= preg_quote(pack('v', strlen($folderName)), '/'); // File name length
		$folderHeaderRegExp .= '.{2,2}'; // Ignore "extra field length"
		$folderHeaderRegExp .= preg_quote($folderName, '/'); // File name
		$folderHeaderRegExp .= '/s'; // PCRE_DOTALL, so all characters (including bytes that happen to be new line characters) match

		// assertRegExp is not used to prevent the whole file from being printed
		// in case of error.
		Assert::assertEquals(
			1, preg_match($folderHeaderRegExp, $this->downloadedFile),
			"Local header for folder did not appear once in zip file"
		);
	}
}