aboutsummaryrefslogtreecommitdiffstats
path: root/build/integration/features/bootstrap/Download.php
blob: ec3b79363e4cf988350ee10af35c8e47af7f4a15 (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
<?php
/**
 * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */
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'
		);
	}
}