/** * Expand archive * * @param bool $cleanup Whether or not to clean up after expansion (i.e. removing known OS files, etc...) * @return bool */ public function expand($cleanup = true) { // Create local tmp copy of the archive that's being expanded $temp = Manager::getTempPath($this->getName()); $this->copy($temp); $zip = new \ZipArchive(); // Open the temp archive (we use the absolute path because we're on the local filesystem) if ($zip->open($temp->getAbsolutePath()) === true) { // We don't actually have to extract the archive, we can just read out of it and copy over to the original location for ($i = 0; $i < $zip->numFiles; $i++) { $filename = $zip->getNameIndex($i); $entity = Entity::fromPath($this->getParent() . '/' . $filename, $this->getAdapter()); if ($entity->isFile()) { // Open $item = fopen('zip://' . $temp->getAbsolutePath() . '#' . $filename, 'r'); // Write stream $entity->putStream($item); // Close fclose($item); } else { // Create the directory $entity->create(); } } // Clean up $zip->close(); $temp->delete(); return parent::expand($cleanup); } return false; }
/** * Expand archive * * @param bool $cleanup Whether or not to clean up after expansion (i.e. removing known OS files, etc...) * @return bool */ public function expand($cleanup = true) { // Create local tmp copy of the archive that's being expanded $temp = Manager::getTempPath($this->getName()); $this->copy($temp); $archive = new \PharData($temp->getAbsolutePath()); foreach ($archive as $file) { // Add 7 to the length for the 'phar://' prefix to the file $path = substr($file, strlen($temp->getAbsolutePath()) + 7); $entity = Entity::fromPath($this->getParent() . $path, $this->getAdapter()); if ($entity->isFile()) { // Open $item = fopen($file, 'r'); // Write stream $entity->putStream($item); // Close fclose($item); } else { // Create the directory $entity->create(); } } // Clean up $temp->delete(); return parent::expand($cleanup); }
/** * Compresses/archives entities in collection * * @param bool $structure Whether or not to retain directory location of files being zipped * @param bool $upload Whether or not to reupload compressed to filesystem location * @return string|bool */ public function compress($structure = false, $upload = false) { if (!extension_loaded('zip')) { return false; } // Get temp directory $adapter = null; $temp = sys_get_temp_dir(); $tarname = uniqid() . '.zip'; $zip = new \ZipArchive(); if ($zip->open($temp . DS . $tarname, \ZipArchive::OVERWRITE) === true) { foreach ($this->_data as $entity) { if ($entity->isFile()) { $zip->addFromString($structure ? $entity->getPath() : $entity->getName(), $entity->read()); } else { if ($entity->isDir() && $structure) { $zip->addEmptyDir($entity->getPath()); } } // Set some vars in case we need them later $adapter = $adapter ?: $entity->getAdapter(); } $zip->close(); $local = Manager::getTempPath(); if ($upload) { // @FIXME: use manager copy? $entity = Entity::fromPath($tarname, $adapter); $entity->put($local->readAndDelete()); return $entity; } else { return $local; } } else { return false; } }
/** * Checks to see if the entity is virus free * * @param bool $remote Whether or not to scan remote files * @return bool **/ public function isSafe($remote = false) { // Get the command // -i says we only want to hear about infected files // -r says scan recursively, this allows scanning a directory, rather than // making multiple calls to scan individual files $command = App::get('config')->get('virus_scanner', 'clamscan -i -r --no-summary --block-encrypted'); // Always scan local, and only scan remote if explicitly requested if ($this->isLocal() || !$this->isLocal() && $remote) { if (!$this->isLocal()) { // Copy to tmp $temp = Manager::getTempPath(uniqid(true) . '.tmp'); $this->copy($temp); $path = $temp->getAbsolutePath(); } else { $path = $this->getAbsolutePath(); } // Build the command if (strstr($command, '%s')) { $command = sprintf($command, escapeshellarg($path)); } else { $command .= ' ' . escapeshellarg($path); } // Execute the scan exec($command, $output, $status); // Get rid of the local copy if needed if (!$this->isLocal()) { $temp->delete(); } // Check the status, 1 means virus found, 2 means there was an error // (these definitions are for clamscan specifically) if ($status >= 1) { return false; } } return true; }
/** * Save incoming file selection * * @return boolean */ public function save($element, $elementId, $pub, $blockParams, $toAttach = array()) { // Incoming selections if (empty($toAttach)) { $selections = Request::getVar('selecteditems', ''); $toAttach = explode(',', $selections); } // Get configs $configs = $this->getConfigs($element, $elementId, $pub, $blockParams); // Cannot make changes if ($configs->freeze) { return false; } // Nothing to change if (empty($toAttach)) { return false; } // Git helper include_once PATH_CORE . DS . 'components' . DS . 'com_projects' . DS . 'helpers' . DS . 'githelper.php'; $this->_git = new \Components\Projects\Helpers\Git($configs->path); // Counter $i = 0; $a = 0; // Attach/refresh each selected item foreach ($toAttach as $identifier) { if (!trim($identifier)) { continue; } $identifier = urldecode($identifier); // Catch items coming in from connections if (preg_match('/^([0-9]*):\\/\\//', $identifier, $matches)) { if (isset($matches[1])) { require_once PATH_CORE . DS . 'components' . DS . 'com_projects' . DS . 'models' . DS . 'orm' . DS . 'connection.php'; // Grab the connection id $connection = $matches[1]; // Reset identifier $identifier = str_replace($matches[0], '', $identifier); $connection = Connection::oneOrFail($connection); // Create file objects $conFile = Entity::fromPath($identifier, $connection->adapter()); if (!$conFile->isLocal()) { // Create a temp file and write to it $tempFile = Manager::getTempPath($conFile->getName()); Manager::copy($conFile, $tempFile); } else { $tempFile = $conFile; } // Insert the file into the repo $result = $pub->_project->repo()->insert(['subdir' => $conFile->getParent(), 'dataPath' => $tempFile->getAbsolutePath(), 'update' => false]); if (!$conFile->isLocal()) { $tempFile->delete(); } } } $a++; $ordering = $i + 1; if ($this->addAttachment($identifier, $pub, $configs, User::get('id'), $elementId, $element, $ordering)) { $i++; } } // Success if ($i > 0 && $i == $a) { Event::trigger('filesystem.onAfterSaveFileAttachments', [$pub, $configs, $elementId, $element]); $message = $this->get('_message') ? $this->get('_message') : Lang::txt('Selection successfully saved'); $this->set('_message', $message); } return true; }