| 1 | <?php |
| 2 | |
| 3 | namespace wcf\system\package; |
| 4 | |
| 5 | use wcf\data\application\Application; |
| 6 | use wcf\data\package\Package; |
| 7 | use wcf\system\database\util\PreparedStatementConditionBuilder; |
| 8 | use wcf\system\exception\SystemException; |
| 9 | use wcf\system\WCF; |
| 10 | |
| 11 | /** |
| 12 | * File handler implementation for the installation of regular files. |
| 13 | * |
| 14 | * @author Matthias Schmidt, Marcel Werk |
| 15 | * @copyright 2001-2019 WoltLab GmbH |
| 16 | * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php> |
| 17 | */ |
| 18 | class FilesFileHandler extends PackageInstallationFileHandler |
| 19 | { |
| 20 | /** |
| 21 | * @inheritDoc |
| 22 | */ |
| 23 | public function checkFiles(array $files) |
| 24 | { |
| 25 | if ($this->packageInstallation->getPackage()->package != 'com.woltlab.wcf') { |
| 26 | if (!empty($files)) { |
| 27 | // get registered files of other packages for the |
| 28 | // same application |
| 29 | $conditions = new PreparedStatementConditionBuilder(); |
| 30 | $conditions->add('packageID <> ?', [$this->packageInstallation->getPackageID()]); |
| 31 | $conditions->add('filename IN (?)', [$files]); |
| 32 | $conditions->add('application = ?', [$this->application]); |
| 33 | |
| 34 | $sql = "SELECT filename, packageID |
| 35 | FROM wcf1_package_installation_file_log |
| 36 | {$conditions}"; |
| 37 | $statement = WCF::getDB()->prepare($sql); |
| 38 | $statement->execute($conditions->getParameters()); |
| 39 | $lockedFiles = $statement->fetchMap('filename', 'packageID'); |
| 40 | |
| 41 | // check delivered files |
| 42 | if (!empty($lockedFiles)) { |
| 43 | foreach ($files as $file) { |
| 44 | if (isset($lockedFiles[$file])) { |
| 45 | $owningPackage = new Package($lockedFiles[$file]); |
| 46 | |
| 47 | throw new SystemException("A package can't overwrite files from other packages. Only an update from the package which owns the file can do that. (Package '" . $this->packageInstallation->getPackage()->package . "' tries to overwrite file '" . $file . "', which is owned by package '" . $owningPackage->package . "')"); |
| 48 | } |
| 49 | } |
| 50 | } |
| 51 | } |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | /** |
| 56 | * @inheritDoc |
| 57 | */ |
| 58 | public function logFiles(array $files) |
| 59 | { |
| 60 | if (empty($files)) { |
| 61 | return; |
| 62 | } |
| 63 | |
| 64 | $baseDirectory = Application::getDirectory($this->application); |
| 65 | |
| 66 | $sql = "INSERT INTO wcf1_package_installation_file_log |
| 67 | (packageID, filename, application, sha256, lastUpdated) |
| 68 | VALUES (?, ?, ?, ?, ?) |
| 69 | ON DUPLICATE KEY UPDATE sha256 = VALUES(sha256), |
| 70 | lastUpdated = VALUES(lastUpdated)"; |
| 71 | $statement = WCF::getDB()->prepare($sql); |
| 72 | |
| 73 | WCF::getDB()->beginTransaction(); |
| 74 | foreach ($files as $file) { |
| 75 | $statement->execute([ |
| 76 | $this->packageInstallation->getPackageID(), |
| 77 | $file, |
| 78 | $this->application, |
| 79 | \hash_file('sha256', $baseDirectory . $file, true), |
| 80 | TIME_NOW, |
| 81 | ]); |
| 82 | } |
| 83 | WCF::getDB()->commitTransaction(); |
| 84 | } |
| 85 | } |