/** * Execute a block of code. * * @param string $code * @param boolean $cache * @param boolean $do_not_eval * @return mixed */ protected static function coreEval(string $code, bool $cache = false, bool $do_not_eval = false) { \clearstatcache(); if ($do_not_eval || \Airship\is_disabled('eval')) { if ($cache) { if (!\file_exists(ROOT . "/tmp/cache/gear")) { \mkdir(ROOT . "/tmp/cache/gear", 0777); \clearstatcache(); } $hashed = Base64UrlSafe::encode(CryptoUtil::raw_hash($code, 33)); if (!\file_exists(ROOT . '/tmp/cache/gear/' . $hashed . '.tmp.php')) { \file_put_contents(ROOT . '/tmp/cache/gear/' . $hashed . '.tmp.php', '<?php' . "\n" . $code); } return self::sandboxRequire(ROOT . '/cache/' . $hashed . '.tmp.php'); } else { if (!\file_exists(ROOT . '/tmp/gear')) { \mkdir(ROOT . '/tmp/gear', 0777); \clearstatcache(); } $file = \Airship\tempnam('gear-', 'php', ROOT . '/tmp/gear'); \file_put_contents($file, '<?php' . "\n" . $code); \clearstatcache(); $ret = self::sandboxRequire($file); \unlink($file); \clearstatcache(); return $ret; } } else { return eval($code); } }
/** * Download an update into a temp file * * @throws TransferException * @param UpdateInfo $update * @param string $apiEndpoint * @return UpdateFile */ public function downloadUpdateFile(UpdateInfo $update, string $apiEndpoint = 'download') : UpdateFile { if ($this->localUpdateFile instanceof UpdateFile) { $this->log('Local update file used', LogLevel::DEBUG); return $this->localUpdateFile; } try { $version = $update->getVersion(); $body = $this->hail->postReturnBody($update->getChannel() . API::get($apiEndpoint), ['type' => \get_class($this), 'supplier' => $update->getSupplierName(), 'package' => $update->getPackageName(), 'version' => $version]); $outFile = \Airship\tempnam('airship-', $this->ext); $saved = \file_put_contents($outFile, $body); if ($saved !== false) { // To prevent TOCTOU issues down the line $hash = Util::hash($body); $body = null; \clearstatcache(); return new UpdateFile(['path' => $outFile, 'version' => $version, 'hash' => $hash, 'size' => \filesize($outFile)]); } // If we're still here... throw new TransferException(); } catch (TransferException $ex) { $this->log('Automatic update failure.', LogLevel::WARNING, ['exception' => \Airship\throwableToArray($ex), 'channel' => $update->getChannel()]); // Rethrow it to prevent errors on return type throw $ex; } }
/** * Download the file from the update server. * * @param array $update * @return InstallFile * @throws TransferException */ public function download(array $update = []) : InstallFile { if ($this->localInstallFile instanceof InstallFile) { self::$continuumLogger->store(LogLevel::DEBUG, 'Local install file used instead of downloading.', ['installFile' => ['hash' => $this->localInstallFile->getHash(), 'path' => $this->localInstallFile->getPath(), 'signature' => $this->localInstallFile->getSignature(), 'size' => $this->localInstallFile->getSize(), 'version' => $this->localInstallFile->getVersion()]]); return $this->localInstallFile; } // If this was not supplied, we need to get it. if (empty($update)) { $update = $this->getPackageData(); } $supplierName = $this->supplier->getName(); \uasort($update['versions'], function (array $a, array $b) : int { return (int) ($a['version'] <=> $b['version']); }); $data = \array_pop($update['versions']); $version = $data['version']; $body = $this->hail->postReturnBody($update['channel'] . API::get('download'), ['type' => \get_class($this), 'supplier' => $supplierName, 'package' => $this->package, 'version' => $version]); $outFile = \Airship\tempnam('airship-', $this->ext); $saved = \file_put_contents($outFile, $body); if ($saved === false) { throw new TransferException(); } // To prevent TOCTOU issues down the line $hash = Util::hash($body); $body = null; \clearstatcache(); return new InstallFile($this->supplier, ['data' => $data, 'hash' => $hash, 'path' => $outFile, 'size' => \filesize($outFile), 'type' => $this->type, 'version' => $version]); }
/** * @covers \Airship\tempnam() */ public function testTempNam() { $name = \Airship\tempnam(); $name2 = \Airship\tempnam('foo-'); $name3 = \Airship\tempnam('foo-', 'txt'); $this->assertFileNotExists($name); $this->assertFileNotExists($name2); $this->assertFileNotExists($name3); $this->assertSame('foo-', Binary::safeSubstr(\Airship\path_to_filename($name3), 0, 4)); $this->assertSame('.txt', Binary::safeSubstr($name3, -4)); }