/** * Install the new version * * If we get to this point: * * 1. We know the signature is signed by the supplier. * 2. The hash was checked into Keyggdrasil, which * was independently vouched for by our peers. * * @param UpdateInfo $info (part of definition but not used here) * @param UpdateFile $file * @throws CouldNotUpdate * @throws MotifZipFailed */ protected function install(UpdateInfo $info, UpdateFile $file) { if (!$file->hashMatches($info->getChecksum())) { throw new CouldNotUpdate(\__('Checksum mismatched')); } // Let's open the update package: $path = $file->getPath(); $zip = new \ZipArchive(); $res = $zip->open($path); if ($res !== true) { throw new MotifZipFailed(\__("ZIP Error: %s", "default", $res)); } $dir = \implode(DIRECTORY_SEPARATOR, [ROOT, 'Motifs', $this->supplier->getName(), $this->name]); // Extract the new files to the current directory if (!$zip->extractTo($dir)) { throw new CouldNotUpdate(); } // Make sure we update the version info. in the DB cache: $this->updateDBRecord('Motif', $info); self::$continuumLogger->store(LogLevel::INFO, 'Motif update installed', $this->getLogContext($info, $file)); }
/** * Install an updated version of a cabin * * If we get to this point: * * 1. We know the signature is signed by the supplier. * 2. The hash was checked into Keyggdrasil, which * was independently vouched for by our peers. * * @param UpdateInfo $info * @param UpdateFile $file * @throws CouldNotUpdate */ protected function install(UpdateInfo $info, UpdateFile $file) { if (!$file->hashMatches($info->getChecksum())) { throw new CouldNotUpdate(\__('Checksum mismatched')); } $path = $file->getPath(); $this->log('Begin Cabin updater', LogLevel::DEBUG, ['path' => $path, 'supplier' => $info->getSupplierName(), 'name' => $info->getPackageName()]); $updater = new \Phar($path, \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::KEY_AS_FILENAME); $updater->setAlias($this->pharAlias); $ns = $this->makeNamespace($info->getSupplierName(), $info->getPackageName()); // We need to do this while we're replacing files. $this->bringCabinDown($ns); $oldMetadata = \Airship\loadJSON(ROOT . '/Cabin/' . $ns . '/manifest.json'); // Overwrite files $updater->extractTo(ROOT . '/Cabin/' . $ns, null, true); // Run the update trigger. Sandbox::safeInclude('phar://' . $this->pharAlias . '/update_trigger.php', $oldMetadata); // Free up the updater alias $garbageAlias = Base64UrlSafe::encode(\random_bytes(33)) . '.phar'; $updater->setAlias($garbageAlias); unset($updater); // Now bring it back up. $this->bringCabinBackUp($ns); // Make sure we update the version info. in the DB cache: $this->updateDBRecord('Cabin', $info); $this->log('Conclude Cabin updater', LogLevel::DEBUG, ['path' => $path, 'supplier' => $info->getSupplierName(), 'name' => $info->getPackageName()]); self::$continuumLogger->store(LogLevel::INFO, 'Cabin update installed', $this->getLogContext($info, $file)); }
/** * Let's install the automatic update. * * If we get to this point: * * 1. We know the signature is signed by * Paragon Initiative Enterprises, LLC. * 2. The hash was checked into Keyggdrasil, which * was independently vouched for by our peers. * * @param UpdateInfo $info * @param UpdateFile $file * @throws CouldNotUpdate */ protected function install(UpdateInfo $info, UpdateFile $file) { if (!$file->hashMatches($info->getChecksum())) { throw new CouldNotUpdate(\__('Checksum mismatched')); } // Let's open the update package: $path = $file->getPath(); $updater = new \Phar($path, \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::KEY_AS_FILENAME); $updater->setAlias($this->pharAlias); $metadata = $updater->getMetadata(); // We need to do this while we're replacing files. $this->bringSiteDown(); if (isset($metadata['files'])) { foreach ($metadata['files'] as $fileName) { $this->replaceFile($fileName); } } if (isset($metadata['autoRun'])) { foreach ($metadata['autoRun'] as $autoRun) { $this->autoRunScript($autoRun); } } // If we included composer.lock, we need to install the dependencies. if (\in_array('composer.lock', $metadata['files'])) { $composers = ['/usr/bin/composer', '/usr/bin/composer.phar', \dirname(ROOT) . '/composer', \dirname(ROOT) . '/composer.phar']; $composerUpdated = false; foreach ($composers as $composer) { if (\file_exists($composer)) { $dir = \getcwd(); \chdir(\dirname(ROOT)); \shell_exec("{$composer} install"); \chdir($dir); $composerUpdated = true; break; } } if (!$composerUpdated) { self::$continuumLogger->store(LogLevel::INFO, 'Could not update dependencies. Please run Composer manually.', $this->getLogContext($info, $file)); } } // Free up the updater alias $garbageAlias = Base64UrlSafe::encode(\random_bytes(63)) . '.phar'; $updater->setAlias($garbageAlias); unset($updater); // Now bring it back up. $this->bringSiteBackUp(); self::$continuumLogger->store(LogLevel::INFO, 'CMS Airship core update installed', $this->getLogContext($info, $file)); }
/** * We just need to replace the Phar * * If we get to this point: * * 1. We know the signature is signed by the supplier. * 2. The hash was checked into Keyggdrasil, which * was independently vouched for by our peers. * * @param UpdateInfo $info * @param UpdateFile $file * @throws CouldNotUpdate */ protected function install(UpdateInfo $info, UpdateFile $file) { if (!$file->hashMatches($info->getChecksum())) { throw new CouldNotUpdate(\__('Checksum mismatched')); } // Create a backup of the old Gadget: \rename($this->filePath, $this->filePath . '.backup'); \rename($file->getPath(), $this->filePath); $this->log('Begin install process', LogLevel::DEBUG, ['path' => $file->getPath(), 'hash' => $file->getHash(), 'version' => $file->getVersion(), 'size' => $file->getSize()]); // Get metadata from the old version of this Gadget: $oldAlias = Base64UrlSafe::encode(\random_bytes(48)) . '.phar'; $oldGadget = new \Phar($this->filePath, \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::KEY_AS_FILENAME); $oldGadget->setAlias($oldAlias); $oldMetadata = $oldGadget->getMetadata(); unset($oldGadget); unset($oldAlias); // Let's open the update package: $newGadget = new \Phar($this->filePath, \FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::KEY_AS_FILENAME, $this->pharAlias); $newGadget->setAlias($this->pharAlias); $metaData = $newGadget->getMetadata(); // We need to do this while we're replacing files. $this->bringSiteDown(); Sandbox::safeRequire('phar://' . $this->pharAlias . '/update_trigger.php', $oldMetadata); // Free up the updater alias $garbageAlias = Base64UrlSafe::encode(\random_bytes(48)) . '.phar'; $newGadget->setAlias($garbageAlias); unset($newGadget); // Now bring it back up. $this->bringSiteBackUp(); // Make sure we update the version info. in the DB cache: $this->updateDBRecord('Gadget', $info); if ($metaData) { $this->updateJSON($info, $metaData); } self::$continuumLogger->store(LogLevel::INFO, 'Gadget update installed', $this->getLogContext($info, $file)); }