/** * Fire the add command! * * @param array $args * @return bool */ public function fire(array $args = []) : bool { try { $this->getSession(); $dir = $this->session['dir'] . $this->findRelativeDir(); } catch (\Error $e) { echo $e->getMessage(), "\n"; return false; } if (\count($args) === 0) { echo 'No file passed.', "\n"; return false; } if (!isset($this->session['add'])) { echo 'Creating session data', "\n"; $this->session['add'] = []; } $added = 0; foreach ($args as $file) { $l = Binary::safeStrlen($file) - 1; if ($file[$l] === DIRECTORY_SEPARATOR) { $file = Binary::safeSubstr($file, 0, -1); } $added += $this->addFile($file, $dir); } echo $added, ' file', $added === 1 ? '' : 's', ' added.', "\n"; return true; }
/** * Request a value. * @param string $text * @return string */ function prompt(string $text = '') { static $fp = null; if ($fp === null) { $fp = \fopen('php://stdin', 'r'); } echo $text; return Binary::safeSubstr(\fgets($fp), 0, -1); }
/** * Work around poorly-configured web servers by parsing out the GET parameters * * Be forewarned: this will overwrite $lastPiece * * @param string& $lastPiece (optional) * @return array */ protected function httpGetParams(string &$lastPiece = null) : array { if ($lastPiece === null) { return $_GET ?? []; } $p = \strpos($lastPiece, '?'); if ($p !== false && empty($_GET)) { $_GET = \Airship\array_from_http_query(Binary::safeSubstr($lastPiece, $p + 1)); $lastPiece = Binary::safeSubstr($lastPiece, 0, $p); } return $_GET; }
/** * If a file path is absolute, but still in the root, truncate it. * If a file path is relative to the root, return it. * Otherwise, thorw an error! * * @param string $file * @return string * @throws \Error */ protected function getRealPath(string $file) : string { if (!\file_exists($file)) { throw new \Error('File not found: ' . $file); } if (\strpos($file, $this->session['dir']) === 0) { $x = Binary::safeStrlen($this->session['dir']); return Binary::safeSubstr($file, $x + 1); } elseif ($file[0] !== DIRECTORY_SEPARATOR) { return $file; } else { throw new \Error('File path is outside the root directory: ' . $file); } }
/** * Load all of the supplier's Ed25519 public keys * * @param string $supplier * @param boolean $force_flush * @return SupplierObject|SupplierObject[] * @throws NoSupplier */ public function getSupplier(string $supplier = '', bool $force_flush = false) { if (empty($supplier)) { // Fetch all suppliers if ($force_flush || empty($this->supplierCache)) { $supplierCache = []; $allSuppliers = \Airship\list_all_files(ROOT . '/config/supplier_keys', 'json'); foreach ($allSuppliers as $supplierKeyFile) { // We want everything except the .json $supplier = $this->escapeSupplierName(Binary::safeSubstr($this->getEndPiece($supplierKeyFile), 0, -5)); try { $data = \Airship\loadJSON($supplierKeyFile); } catch (FileNotFound $ex) { $data = []; } $supplierCache[$supplier] = new SupplierObject($supplier, $data); } $this->supplierCache = $supplierCache; } return $this->supplierCache; } // Otherwise, we're just fetching one supplier's keys if ($force_flush || empty($this->supplierCache[$supplier])) { try { $supplier = $this->escapeSupplierName($supplier); $supplierFile = ROOT . '/config/supplier_keys/' . $supplier . '.json'; if (!\file_exists($supplierFile)) { throw new NoSupplier(\__("Supplier file not found: %s", "default", $supplierFile)); } $data = \Airship\loadJSON($supplierFile); } catch (FileNotFound $ex) { throw new NoSupplier(\__("Supplier not found: %s", "default", $supplier), 0, $ex); } $this->supplierCache[$supplier] = new SupplierObject($supplier, $data); } if (isset($this->supplierCache[$supplier])) { return $this->supplierCache[$supplier]; } throw new NoSupplier(); }
<?php declare (strict_types=1); use ParagonIE\ConstantTime\Binary; require_once \dirname(__DIR__) . '/src/bootstrap.php'; /** * Grabs a random file and tells you to audit it. */ if ($argc > 1) { $extensions = \array_slice($argv, 1); } else { $extensions = ['php', 'twig']; } $fileList = []; foreach ($extensions as $ex) { foreach (\Airship\list_all_files(\dirname(__DIR__) . '/src/', $ex) as $file) { $fileList[] = $file; } } $choice = \random_int(0, \count($fileList) - 1); echo "Audit this file:\n\t"; $l = Binary::safeStrlen(\dirname(__DIR__)); echo Binary::safeSubstr($fileList[$choice], $l), "\n";
/** * WordPress's internal password hashing algorithm. Only used for migrations. * The actual security of CMS Airship doesn't depend on this algorithm. * * @internal * @param HiddenString $password * @param string $setting * @return string */ private function wordPressCryptPrivate(HiddenString $password, string $setting) : string { $output = '*0'; if (Binary::safeSubstr($setting, 0, 2) === $output) { $output = '*1'; } $id = Binary::safeSubstr($setting, 0, 3); if ($id !== '$P$' && $id !== '$H$') { return $output; } // This is a really weird way to encode iteration count. $count_log2 = \strpos($this->itoa64, $setting[3]); if ($count_log2 < 7 || $count_log2 > 30) { return $output; } $count = 1 << $count_log2; $salt = Binary::safeSubstr($setting, 4, 8); if (Binary::safeStrlen($salt) !== 8) { return $output; } // And now we do our (default 8192) rounds of MD5... $hash = \md5($salt . $password->getString(), true); do { $hash = \md5($hash . $password->getString(), true); } while (--$count); $output = Binary::safeSubstr($setting, 0, 12); $output .= $this->encode64($hash, 16); return $output; }
/** * Binary-safe substr() implementation * * @param string $str * @param int $start * @param int|null $length * @return string */ public static function subString(string $str, int $start, $length = null) : string { return Binary::safeSubstr($str, $start, $length); }
/** * Configure the application event logger here */ $log_setup_closure = function () { $state = State::instance(); $loggerClass = Gears::getName('Ledger'); $args = []; /** * Here we build our logger storage class */ switch ($state->universal['ledger']['driver']) { case 'file': $path = $state->universal['ledger']['path']; if (Binary::safeStrlen($path) >= 2) { if ($path[0] === '~' && $path[1] === '/') { $path = ROOT . '/' . Binary::safeSubstr($path, 2); } } $storage = new FileStore($path, $state->universal['ledger']['file-format'] ?? FileStore::FILE_FORMAT, $state->universal['ledger']['time-format'] ?? FileStore::TIME_FORMAT); break; case 'database': $path = $state->universal['ledger']['connection']; try { $storage = new DBStore($path, $state->universal['ledger']['table'] ?? DBStore::DEFAULT_TABLE); } catch (\Throwable $ex) { \http_response_code(500); echo \file_get_contents(__DIR__ . '/error_pages/uncaught-exception.html'); if ($state->universal['debug']) { echo '<pre>', $ex->getTraceAsString(), '</pre>'; } exit(1);
<?php declare (strict_types=1); use ParagonIE\ConstantTime\Binary; /** * Paragon Initiative Enterprises * PSR-4 compatible autoloader */ \spl_autoload_register(function ($class) { // Project-specific namespace prefix $prefix = 'Airship\\Hangar'; // Base directory for the namespace prefix $base_dir = __DIR__ . DIRECTORY_SEPARATOR; // Does the class use the namespace prefix? $len = \strlen($prefix); if (\strncmp($prefix, $class, $len) !== 0) { // no, move to the next registered autoloader return; } // Get the relative class name $relative_class = Binary::safeSubstr($class, $len); // Replace the namespace prefix with the base directory, replace namespace // separators with directory separators in the relative class name, append // with .php $file = $base_dir . \str_replace(['\\', '_'], DIRECTORY_SEPARATOR, $relative_class) . '.php'; // If the file exists, require it if (\file_exists($file)) { require $file; } });
/** * Actually serve the HTTP request */ public function route() { $this->loadInjectedRoutes(); $args = []; foreach ($this->cabin['data']['routes'] as $path => $landing) { $path = self::makePath($path); if (self::testLanding($path, $_SERVER['REQUEST_URI'], $args)) { self::$mypath = $path; self::$path = Binary::safeSubstr($_SERVER['REQUEST_URI'], Binary::safeStrlen(self::$patternPrefix) + 1); try { // Attempt to serve the page: return $this->serve($landing, \array_slice($args, 1)); } catch (EmulatePageNotFound $ex) { // If this exception is throw, we will attempt to serve // the fallback route (which might end up with a 404 page) return $this->serveFallback(); } } } return $this->serveFallback(); }
$link = ROOT . '/public/static/' . $active['name']; if (!\is_link($link)) { // Remove copies, we only allow symlinks in static if (\is_dir($link)) { \rmdir($link); } elseif (\file_exists($link)) { \unlink($link); } // Create a symlink from public/static/* to Cabin/*/public /** @noinspection PhpUsageOfSilenceOperatorInspection */ @\symlink(CABIN_DIR . '/public', ROOT . '/public/static/' . $active['name']); } } // Let's load the default cargo modules if (\is_dir(CABIN_DIR . '/Lens/cargo')) { $cargoCacheFile = ROOT . '/tmp/cache/cargo-' . $active['name'] . '.cache.json'; if (\file_exists($cargoCacheFile)) { $data = Airship\loadJSON($cargoCacheFile); $state->cargo = $data; } else { $dir = \getcwd(); \chdir(CABIN_DIR . '/Lens'); foreach (\Airship\list_all_files('cargo', 'twig') as $cargo) { $idx = \str_replace(['__', '/'], ['', '__'], Binary::safeSubstr($cargo, 6, -5)); Gadgets::loadCargo($idx, $cargo); } \chdir($dir); // Store the cache file \Airship\saveJSON($cargoCacheFile, $state->cargo); } }
/** * @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)); }
} /** * Let the user know precisely what's wrong, if anything is wrong. */ if (!Halite::isLibsodiumSetupCorrectly()) { // Easiest way to grab this info: \ob_start(); \phpinfo(); $data = \ob_get_clean(); $version = ''; foreach (\explode("\n", $data) as $line) { if (empty($line)) { continue; } if (\strpos($line, 'libsodium compiled version') !== false) { $version = \trim(Binary::safeSubstr(\trim($line), -6)); break; } } die("Your libsodium is not setup correctly. Please make sure you have at least:\n\n" . "\tlibsodium v1.0.10 (Installed: " . \Sodium\version_string() . ")\n" . "\tlibsodium-php v1.0.6 (Installed: " . $version . ")\n"); } /** * 3. Process the CLI parameters */ $showAll = true; if ($argc < 2) { // Default behavior: Display the help menu $argv[1] = 'help'; $showAll = false; $argc = 2; }