protected function body() { if (!$this->userHasPrivileges(User::pluginsAdd)) { return false; } $inputs = array('name' => array('isName', 'isNotEmpty')); if (!$this->isInputValid($inputs)) { return false; } $name = $this->getParams('name'); $existingPluginsWithSameName = Repositories::getRepository(Repositories::Plugin)->findBy(['name' => $name]); if (count($existingPluginsWithSameName) > 0) { return $this->death(StringID::PluginNameAlreadyExists); } $pluginFile = $this->getUploadedFile('plugin'); if (!$pluginFile) { return false; } $pluginFolder = Config::get('paths', 'plugins') . $name; if (file_exists($pluginFolder)) { return $this->death(StringID::PluginFolderAlreadyExists); } if (!Filesystem::createDir($pluginFolder)) { return $this->death(StringID::FileSystemError); } if (!Compression::unzip($pluginFile, $pluginFolder)) { $this->death(StringID::UnzipUnsuccessful); goto cleanup_error; } $manifestFile = $pluginFolder . DIRECTORY_SEPARATOR . 'manifest.xml'; $manifest = null; if (!($manifest = $this->parsePluginManifest($manifestFile))) { $this->death(StringID::BadlyFormedPlugin); goto cleanup_error; } if (!file_exists($pluginFolder . DIRECTORY_SEPARATOR . $manifest['mainFile'])) { $this->death(StringID::BadlyFormedPlugin); goto cleanup_error; } $plugin = new \Plugin(); $plugin->setIdentifier($manifest['identifier']); $plugin->setDescription($manifest['description']); $plugin->setConfig($manifest['arguments']); $plugin->setMainfile($name . '/' . $manifest['mainFile']); $plugin->setName($name); $plugin->setType($manifest['type']); Repositories::persistAndFlush($plugin); Filesystem::removeFile($pluginFile); return true; cleanup_error: Filesystem::removeDir($pluginFolder); Filesystem::removeFile($pluginFile); return false; }
public function testRotation() { if (file_exists('log')) { rmdir('log'); } mkdir("log"); $logger = Logger::create("log")->setDatetimeFormat("")->setEntrySeparator("")->setLineSeparator("")->setPrefix("l")->setSuffix("")->setMaxFileCount(4)->setMaxFileSize(10)->setHeader(""); // Header is therefore one space that separates the (empty) date from the (empty) header text $logger->log("A23456789"); $logger->flush(); $logger->log("B23456789"); $logger->flush(); $logger->log("C23456789"); $logger->flush(); $logger->log("D23456789"); $logger->flush(); $logger->log("E23456789"); $logger->flush(); $logger->log("F23456789"); $logger->flush(); $logger->log("G23456789"); $logger->flush(); // We have filled 7 files, and maximum file count is 4. // It should have gone: // A l0 // B l0, l1 // C l0, l1, l2 // D l0, l1, l2, l3 // E l1, l2, l3, l4 // F l0, l2, l3, l4 // G l0, l1, l3, l4, where l1 is newest and l3 oldest $this->assertFileExists('log/l0'); $this->assertFileExists('log/l1'); $this->assertFileNotExists('log/l2'); $this->assertFileExists('log/l3'); $this->assertFileExists('log/l4'); $this->assertFileNotExists('log/l5'); $this->assertFileNotExists('log/l6'); $this->assertFileNotExists('log/l7'); $this->assertSame(' D23456789', file_get_contents('log/l3')); $this->assertSame(' E23456789', file_get_contents('log/l4')); $this->assertSame(' F23456789', file_get_contents('log/l0')); $this->assertSame(' G23456789', file_get_contents('log/l1')); \asm\utils\Filesystem::removeDir("log"); }
protected function body() { if (!$this->userHasPrivileges(User::pluginsRemove)) { return false; } if (!$this->isInputValid(array('id' => 'isIndex'))) { return false; } $id = $this->getParams('id'); /** * @var $plugin \Plugin */ $plugin = Repositories::findEntity(Repositories::Plugin, $id); $pluginFolder = Filesystem::combinePaths(Config::get('paths', 'plugins'), $plugin->getName()); if (!Filesystem::removeDir($pluginFolder)) { return $this->death(StringID::FileSystemError); } RemovalManager::deletePluginById($id); return true; }
/** * 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; }
public function testTempDir() { $folder = Filesystem::tempDir(null, "hello"); $this->assertStringStartsWith('hello', basename($folder)); $this->assertTrue(is_dir($folder)); $this->assertEquals(0, count(array_diff(scandir($folder), ['.', '..']))); $this->assertTrue(Filesystem::removeDir($folder)); $this->assertFalse(is_dir($folder)); }
/** * Runs plugin with supplied arguments. * * @li First element in @c $args must be a path to ZIP archive with input data. * @li Plugin execution is stopped on all triggered errors or uncaught exceptions * and plugin error is returned. * @li setUp() and execute() methods are run respectively after input is * unpacked and output folder is created. * @li Plugin creates and later removes two temporary folders. It can also create * one ZIP archive with plugin output (path is returned in plugin results). * * @param array $args simple array with plugin arguments * @return PluginResponse plugin results or error */ public final function run(array $args) { set_error_handler(array('asm\\utils\\Utils', 'turnErrorToException')); $cwd = getcwd(); try { if ($args == null || count($args) < 1) { throw new PluginUseException('Data file argument missing'); } $this->dataFolder = Filesystem::tempDir(); $dataFile = array_shift($args); if (!Compression::unzip($dataFile, $this->dataFolder, $unzipMessage)) { $response = PluginResponse::createError("ZIP extraction failed (" . $unzipMessage . ").\n\nPerhaps you did not submit a ZIP file " . "or that file was corrupted during upload. You may try again. Extraction was attempted to folder " . str_replace("\\", "/", $this->dataFolder)); } else { $this->outputFolder = Filesystem::tempDir(); chdir($this->dataFolder); $this->setUp($args); $this->execute(); chdir($cwd); $outputFile = $this->packOutput(); $outputPath = $outputFile != null ? realpath($outputFile) : null; $response = PluginResponse::create($this->results, $outputPath); } } catch (PluginException $e) { $response = PluginResponse::createError($e->getMessage()); } catch (Exception $e) { $response = PluginResponse::createError('Runtime error: ' . $e->getMessage() . " (file " . $e->getFile() . ", line " . $e->getLine()); } // If an exception occurred during $this->setUp or $this->execute, we must still change the current directory back, // in case more plugins are to be run (in a test case battery) chdir($cwd); restore_error_handler(); if ($this->dataFolder != null) { Filesystem::removeDir($this->dataFolder); } if ($this->outputFolder != null) { Filesystem::removeDir($this->outputFolder); } return $response; }