Download.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2018, Daniel Calviño Sánchez (danxuliu@gmail.com)
  4. *
  5. * @author Daniel Calviño Sánchez <danxuliu@gmail.com>
  6. * @author John Molakvoæ <skjnldsv@protonmail.com>
  7. *
  8. * @license GNU AGPL version 3 or any later version
  9. *
  10. * This program is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU Affero General Public License as
  12. * published by the Free Software Foundation, either version 3 of the
  13. * License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU Affero General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Affero General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. *
  23. */
  24. use PHPUnit\Framework\Assert;
  25. require __DIR__ . '/../../vendor/autoload.php';
  26. trait Download {
  27. /** @var string **/
  28. private $downloadedFile;
  29. /** @AfterScenario **/
  30. public function cleanupDownloadedFile() {
  31. $this->downloadedFile = null;
  32. }
  33. /**
  34. * @When user :user downloads zip file for entries :entries in folder :folder
  35. */
  36. public function userDownloadsZipFileForEntriesInFolder($user, $entries, $folder) {
  37. $this->asAn($user);
  38. $this->sendingToDirectUrl('GET', "/index.php/apps/files/ajax/download.php?dir=" . $folder . "&files=[" . $entries . "]");
  39. $this->theHTTPStatusCodeShouldBe('200');
  40. $this->getDownloadedFile();
  41. }
  42. private function getDownloadedFile() {
  43. $this->downloadedFile = '';
  44. $body = $this->response->getBody();
  45. while (!$body->eof()) {
  46. $this->downloadedFile .= $body->read(8192);
  47. }
  48. $body->close();
  49. }
  50. /**
  51. * @Then the downloaded zip file is a zip32 file
  52. */
  53. public function theDownloadedZipFileIsAZip32File() {
  54. // assertNotContains is not used to prevent the whole file from being
  55. // printed in case of error.
  56. Assert::assertTrue(
  57. strpos($this->downloadedFile, "\x50\x4B\x06\x06") === false,
  58. "File contains the zip64 end of central dir signature"
  59. );
  60. }
  61. /**
  62. * @Then the downloaded zip file is a zip64 file
  63. */
  64. public function theDownloadedZipFileIsAZip64File() {
  65. // assertNotContains is not used to prevent the whole file from being
  66. // printed in case of error.
  67. Assert::assertTrue(
  68. strpos($this->downloadedFile, "\x50\x4B\x06\x06") !== false,
  69. "File does not contain the zip64 end of central dir signature"
  70. );
  71. }
  72. /**
  73. * @Then the downloaded zip file contains a file named :fileName with the contents of :sourceFileName from :user data
  74. */
  75. public function theDownloadedZipFileContainsAFileNamedWithTheContentsOfFromData($fileName, $sourceFileName, $user) {
  76. $fileHeaderRegExp = '/';
  77. $fileHeaderRegExp .= "\x50\x4B\x03\x04"; // Local file header signature
  78. $fileHeaderRegExp .= '.{22,22}'; // Ignore from "version needed to extract" to "uncompressed size"
  79. $fileHeaderRegExp .= preg_quote(pack('v', strlen($fileName)), '/'); // File name length
  80. $fileHeaderRegExp .= '(.{2,2})'; // Get "extra field length"
  81. $fileHeaderRegExp .= preg_quote($fileName, '/'); // File name
  82. $fileHeaderRegExp .= '/s'; // PCRE_DOTALL, so all characters (including bytes that happen to be new line characters) match
  83. // assertRegExp is not used to prevent the whole file from being printed
  84. // in case of error and to be able to get the extra field length.
  85. Assert::assertEquals(
  86. 1, preg_match($fileHeaderRegExp, $this->downloadedFile, $matches),
  87. "Local header for file did not appear once in zip file"
  88. );
  89. $extraFieldLength = unpack('vextraFieldLength', $matches[1])['extraFieldLength'];
  90. $expectedFileContents = file_get_contents($this->getDataDirectory() . "/$user/files" . $sourceFileName);
  91. $fileHeaderAndContentRegExp = '/';
  92. $fileHeaderAndContentRegExp .= "\x50\x4B\x03\x04"; // Local file header signature
  93. $fileHeaderAndContentRegExp .= '.{22,22}'; // Ignore from "version needed to extract" to "uncompressed size"
  94. $fileHeaderAndContentRegExp .= preg_quote(pack('v', strlen($fileName)), '/'); // File name length
  95. $fileHeaderAndContentRegExp .= '.{2,2}'; // Ignore "extra field length"
  96. $fileHeaderAndContentRegExp .= preg_quote($fileName, '/'); // File name
  97. $fileHeaderAndContentRegExp .= '.{' . $extraFieldLength . ',' . $extraFieldLength . '}'; // Ignore "extra field"
  98. $fileHeaderAndContentRegExp .= preg_quote($expectedFileContents, '/'); // File contents
  99. $fileHeaderAndContentRegExp .= '/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($fileHeaderAndContentRegExp, $this->downloadedFile),
  104. "Local header and contents for file did not appear once in zip file"
  105. );
  106. }
  107. /**
  108. * @Then the downloaded zip file contains a folder named :folderName
  109. */
  110. public function theDownloadedZipFileContainsAFolderNamed($folderName) {
  111. $folderHeaderRegExp = '/';
  112. $folderHeaderRegExp .= "\x50\x4B\x03\x04"; // Local file header signature
  113. $folderHeaderRegExp .= '.{22,22}'; // Ignore from "version needed to extract" to "uncompressed size"
  114. $folderHeaderRegExp .= preg_quote(pack('v', strlen($folderName)), '/'); // File name length
  115. $folderHeaderRegExp .= '.{2,2}'; // Ignore "extra field length"
  116. $folderHeaderRegExp .= preg_quote($folderName, '/'); // File name
  117. $folderHeaderRegExp .= '/s'; // PCRE_DOTALL, so all characters (including bytes that happen to be new line characters) match
  118. // assertRegExp is not used to prevent the whole file from being printed
  119. // in case of error.
  120. Assert::assertEquals(
  121. 1, preg_match($folderHeaderRegExp, $this->downloadedFile),
  122. "Local header for folder did not appear once in zip file"
  123. );
  124. }
  125. }