Download.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. <?php
  2. /**
  3. * SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
  4. * SPDX-License-Identifier: AGPL-3.0-or-later
  5. */
  6. use PHPUnit\Framework\Assert;
  7. require __DIR__ . '/../../vendor/autoload.php';
  8. trait Download {
  9. /** @var string * */
  10. private $downloadedFile;
  11. /** @AfterScenario **/
  12. public function cleanupDownloadedFile() {
  13. $this->downloadedFile = null;
  14. }
  15. /**
  16. * @When user :user downloads zip file for entries :entries in folder :folder
  17. */
  18. public function userDownloadsZipFileForEntriesInFolder($user, $entries, $folder) {
  19. $this->asAn($user);
  20. $this->sendingToDirectUrl('GET', '/index.php/apps/files/ajax/download.php?dir=' . $folder . '&files=[' . $entries . ']');
  21. $this->theHTTPStatusCodeShouldBe('200');
  22. $this->getDownloadedFile();
  23. }
  24. private function getDownloadedFile() {
  25. $this->downloadedFile = '';
  26. $body = $this->response->getBody();
  27. while (!$body->eof()) {
  28. $this->downloadedFile .= $body->read(8192);
  29. }
  30. $body->close();
  31. }
  32. /**
  33. * @Then the downloaded zip file is a zip32 file
  34. */
  35. public function theDownloadedZipFileIsAZip32File() {
  36. // assertNotContains is not used to prevent the whole file from being
  37. // printed in case of error.
  38. Assert::assertTrue(
  39. strpos($this->downloadedFile, "\x50\x4B\x06\x06") === false,
  40. 'File contains the zip64 end of central dir signature'
  41. );
  42. }
  43. /**
  44. * @Then the downloaded zip file is a zip64 file
  45. */
  46. public function theDownloadedZipFileIsAZip64File() {
  47. // assertNotContains is not used to prevent the whole file from being
  48. // printed in case of error.
  49. Assert::assertTrue(
  50. strpos($this->downloadedFile, "\x50\x4B\x06\x06") !== false,
  51. 'File does not contain the zip64 end of central dir signature'
  52. );
  53. }
  54. /**
  55. * @Then the downloaded zip file contains a file named :fileName with the contents of :sourceFileName from :user data
  56. */
  57. public function theDownloadedZipFileContainsAFileNamedWithTheContentsOfFromData($fileName, $sourceFileName, $user) {
  58. $fileHeaderRegExp = '/';
  59. $fileHeaderRegExp .= "\x50\x4B\x03\x04"; // Local file header signature
  60. $fileHeaderRegExp .= '.{22,22}'; // Ignore from "version needed to extract" to "uncompressed size"
  61. $fileHeaderRegExp .= preg_quote(pack('v', strlen($fileName)), '/'); // File name length
  62. $fileHeaderRegExp .= '(.{2,2})'; // Get "extra field length"
  63. $fileHeaderRegExp .= preg_quote($fileName, '/'); // File name
  64. $fileHeaderRegExp .= '/s'; // PCRE_DOTALL, so all characters (including bytes that happen to be new line characters) match
  65. // assertRegExp is not used to prevent the whole file from being printed
  66. // in case of error and to be able to get the extra field length.
  67. Assert::assertEquals(
  68. 1, preg_match($fileHeaderRegExp, $this->downloadedFile, $matches),
  69. 'Local header for file did not appear once in zip file'
  70. );
  71. $extraFieldLength = unpack('vextraFieldLength', $matches[1])['extraFieldLength'];
  72. $expectedFileContents = file_get_contents($this->getDataDirectory() . "/$user/files" . $sourceFileName);
  73. $fileHeaderAndContentRegExp = '/';
  74. $fileHeaderAndContentRegExp .= "\x50\x4B\x03\x04"; // Local file header signature
  75. $fileHeaderAndContentRegExp .= '.{22,22}'; // Ignore from "version needed to extract" to "uncompressed size"
  76. $fileHeaderAndContentRegExp .= preg_quote(pack('v', strlen($fileName)), '/'); // File name length
  77. $fileHeaderAndContentRegExp .= '.{2,2}'; // Ignore "extra field length"
  78. $fileHeaderAndContentRegExp .= preg_quote($fileName, '/'); // File name
  79. $fileHeaderAndContentRegExp .= '.{' . $extraFieldLength . ',' . $extraFieldLength . '}'; // Ignore "extra field"
  80. $fileHeaderAndContentRegExp .= preg_quote($expectedFileContents, '/'); // File contents
  81. $fileHeaderAndContentRegExp .= '/s'; // PCRE_DOTALL, so all characters (including bytes that happen to be new line characters) match
  82. // assertRegExp is not used to prevent the whole file from being printed
  83. // in case of error.
  84. Assert::assertEquals(
  85. 1, preg_match($fileHeaderAndContentRegExp, $this->downloadedFile),
  86. 'Local header and contents for file did not appear once in zip file'
  87. );
  88. }
  89. /**
  90. * @Then the downloaded zip file contains a folder named :folderName
  91. */
  92. public function theDownloadedZipFileContainsAFolderNamed($folderName) {
  93. $folderHeaderRegExp = '/';
  94. $folderHeaderRegExp .= "\x50\x4B\x03\x04"; // Local file header signature
  95. $folderHeaderRegExp .= '.{22,22}'; // Ignore from "version needed to extract" to "uncompressed size"
  96. $folderHeaderRegExp .= preg_quote(pack('v', strlen($folderName)), '/'); // File name length
  97. $folderHeaderRegExp .= '.{2,2}'; // Ignore "extra field length"
  98. $folderHeaderRegExp .= preg_quote($folderName, '/'); // File name
  99. $folderHeaderRegExp .= '/s'; // PCRE_DOTALL, so all characters (including bytes that happen to be new line characters) match
  100. // assertRegExp is not used to prevent the whole file from being printed
  101. // in case of error.
  102. Assert::assertEquals(
  103. 1, preg_match($folderHeaderRegExp, $this->downloadedFile),
  104. 'Local header for folder did not appear once in zip file'
  105. );
  106. }
  107. }