public function testCopyIntoDirectory()
 {
     // Copy directory
     $whereTo = "whereTo/inside/";
     $this->assertFalse(is_dir($whereTo));
     $this->assertTrue(Filesystem::copyIntoDirectory(self::TEST_DIRECTORY, $whereTo));
     $this->assertTrue(is_dir($whereTo));
     $this->assertTrue(is_file($whereTo . "a.txt"));
     $this->assertTrue(is_file($whereTo . "b.txt"));
     Filesystem::removeDir($whereTo);
     $this->assertFalse(is_dir($whereTo));
     // Copy into file fails
     touch("whereToFile");
     $this->assertTrue(is_file("whereToFile"));
     $this->assertFalse(Filesystem::copyIntoDirectory(self::TEST_DIRECTORY . "/a.txt", "whereToFile"));
     $this->assertFalse(Filesystem::copyIntoDirectory(self::TEST_DIRECTORY, "whereToFile"));
     $this->assertTrue(is_file('whereToFile'));
     unlink('whereToFile');
     // Copy file into directory
     $this->assertFalse(is_dir($whereTo));
     $this->assertTrue(Filesystem::copyIntoDirectory(self::TEST_DIRECTORY . "/a.txt", Filesystem::combinePaths($whereTo)));
     $this->assertTrue(is_dir($whereTo));
     $this->assertTrue(is_file($whereTo . "a.txt"));
     $this->assertFalse(is_file($whereTo . "b.txt"));
     Filesystem::removeDir($whereTo);
     $this->assertFalse(is_dir($whereTo));
 }
 /**
  * Unpack ZIP archive to specified folder.
  * If it contains only a single directory and nothing else, its contents are extracted instead of the entire ZIP file. This also happens if the only other directory is the "__MACOSX" metadata folder that Macintosh operating systems add to generated ZIP files.
  *
  * This function is a security vulnerability. Possible attacks include a very large ZIP file, such as a ZIP bomb, or putting in a file with a relative path such as '../etc/passwd'.
  *
  *
  * @param string $archive source archive path
  * @param string $destination destination folder path
  * @param [out]string $errorMessage why did the extraction fail?
  * @return true on success
  */
 public static function unzip($archive, $destination, &$errorMessage = null)
 {
     $zip = new ZipArchive();
     $errorCode = $zip->open($archive);
     if ($errorCode !== true) {
         $errorMessage = "could not open ZIP file (error code " . $errorCode . ")";
         return false;
     }
     // Otherwise, this is a normal ZIP file.
     if (!$zip->extractTo($destination)) {
         $zip->close();
         $errorMessage = "extraction failed";
         return false;
     }
     $zip->close();
     // Now, we'll check if the ZIP file contains only a single folder. If so,
     // then we'll copy its contests to the root temporary folder, then remove the original folder.
     $files = scandir($destination);
     if ($files === false) {
         $errorMessage = "scanning the temporary directory failed";
         return false;
     }
     // On Linux, scandir returns the "." and ".." pseudofolders we are not interested in
     $files = array_diff($files, [".", ".."]);
     // For ZIP files generated on Mac OS X, we are not interested in the metadata folder.
     $files = array_diff($files, ["__MACOSX"]);
     if (count($files) === 0) {
         $errorMessage = "the ZIP file is empty";
         return false;
     } elseif (count($files) === 1) {
         // We renumber the remaining file/directory so that it is at index 0. It might not have been because of the subtraction of "." and ".."
         $files = array_values($files);
         $soleDirectory = Filesystem::combinePaths($destination, $files[0]);
         if (is_dir($soleDirectory)) {
             if (Filesystem::copyIntoDirectory($soleDirectory, $destination)) {
                 Filesystem::removeDir($soleDirectory);
                 return true;
             } else {
                 $errorMessage = "the ZIP file contained a single directory, but copying its contents to temporary directory failed";
                 return false;
             }
         }
     }
     return true;
 }