/** * Use firstlevel.second_level.thirdLevel to find indices in an array * * Doesn't apply filters * * @param string $key * @param array $multiDimensional * @return mixed */ public function getUnfilteredValue(string $key, array $multiDimensional = []) { $pieces = \Airship\chunk($key, '.'); $value = $multiDimensional; foreach ($pieces as $piece) { if (!isset($value[$piece])) { return null; } $value = $value[$piece]; } return $value; }
/** * Download a file (assuming we are allowed to) * * @param string $path * @param string $default Default MIME type * @route files/(.*) * @throws EmulatePageNotFound */ public function download(string $path, string $default = 'text/plain') { if (!$this->can('read')) { throw new EmulatePageNotFound(); } $pieces = \Airship\chunk($path); $filename = \array_pop($pieces); try { $fileData = $this->files->getFileInfo($this->cabin, $pieces, \urldecode($filename)); $realPath = AIRSHIP_UPLOADS . $fileData['realname']; if (!\file_exists($realPath)) { throw new FileNotFound(); } $fileData['type'] = Util::downloadFileType($fileData['type'], $default); $c = $this->config('file.cache'); if ($c > 0) { // Use caching \header('Cache-Control: private, max-age=' . $c); \header('Pragma: cache'); } // Serve the file \header('Content-Type: ' . $fileData['type']); /** * The following headers are necessary because Microsoft Internet * Explorer has a documented design flaw that, left unhandled, can * introduce a stored XSS vulnerability. The recommended solution * would be "never use Internet Explorer", but some people don't have * a choice in that matter. */ if (!$this->isViewable($fileData['type'])) { \header('Content-Disposition: attachment; filename="' . \urlencode($fileData['filename']) . '"'); \header('X-Download-Options: noopen'); } \header('X-Content-Type-Options: nosniff'); $this->airship_lens_object->sendStandardHeaders($fileData['type']); \readfile($realPath); exit; } catch (FileNotFound $ex) { // When all else fails, 404 not found \http_response_code(404); $this->lens('404'); exit(1); } }
/** * Given a file path, only return the file name. Optionally, trim the * extension. * * @param string $fullPath * @param bool $trimExtension * @return string */ function path_to_filename(string $fullPath, bool $trimExtension = false) : string { $pieces = \Airship\chunk($fullPath); $lastPiece = \array_pop($pieces); if ($trimExtension) { $parts = \Airship\chunk($lastPiece, '.'); \array_pop($parts); return \implode('.', $parts); } return $lastPiece; }
/** * Move/rename a file * * @param array $fileInfo * @param array $post * @param string $cabin * @return bool */ public function moveFile(array $fileInfo, array $post, string $cabin) : bool { $this->db->beginTransaction(); // Get the directory IDs... $nc = empty($root) ? $post['new_dir'] : $root . '/' . $post['new_dir']; try { if (empty($nc)) { $newDir = null; } else { $newDir = $this->getDirectoryId(\Airship\chunk($nc), $cabin); } } catch (FileNotFound $ex) { $this->db->rollBack(); return false; } if ($newDir === $fileInfo['directory'] && $post['new_name'] === $fileInfo['filename']) { // NOP $this->db->rollBack(); return false; } if ($newDir === null) { $exists = $this->db->exists('SELECT count(*) FROM airship_files WHERE directory IS NULL AND cabin = ? AND filename = ? AND fileid != ?', $cabin, $post['new_name'], $fileInfo['fileid']); $update = ['directory' => null, 'cabin' => $cabin, 'filename' => $post['new_name']]; } else { $exists = $this->db->exists('SELECT count(*) FROM airship_files WHERE directory = ? AND filename = ? AND fileid != ?', $newDir, $post['new_name'], $fileInfo['fileid']); $update = ['directory' => $newDir, 'filename' => $post['new_name']]; } if ($exists) { // There's already a directory here with the same name $this->db->rollBack(); return false; } $this->db->update('airship_files', $update, ['fileid' => $fileInfo['fileid']]); return $this->db->commit(); }
/** * Reduce code duplication * * @param string $path * @param string $cabin * @return array (array $publicPath, int|null $root) */ protected function loadCommonData(string $path, string $cabin) : array { if (!$this->permCheck()) { \Airship\redirect($this->airship_cabin_prefix); } $root = null; $publicPath = \Airship\chunk($path); $pathInfo = $this->getPath($path); if (!empty($pathInfo)) { try { $root = $this->files->getDirectoryId($pathInfo, $cabin); } catch (FileNotFound $ex) { \Airship\redirect($this->airship_cabin_prefix); } } // return [$pathInfo, $publicPath, $root]; return [$publicPath, $root]; }
/** * @covers \Airship\chunk() */ public function testChunk() { $this->assertSame(['foo', 'bar', 'baz'], \Airship\chunk('foo/bar/baz')); $this->assertSame(['foo', 'bar', 'baz'], \Airship\chunk('/foo/bar/baz/')); $this->assertSame(['foo/bar/baz'], \Airship\chunk('foo/bar/baz', '?')); }
/** * We're going to view a page's history * * @route pages/{string}/history/view/{string} * @param string $cabin * @param string $uniqueId */ public function pageHistoryView(string $cabin, string $uniqueId) { $page = []; $version = []; $path = $this->determinePath($cabin); if (!\is1DArray($_GET)) { \Airship\redirect($this->airship_cabin_prefix . '/pages/' . \trim($cabin, '/')); } $cabins = $this->getCabinNamespaces(); if (!\in_array($cabin, $cabins)) { \Airship\redirect($this->airship_cabin_prefix); } $this->setTemplateExtraData($cabin); if (!$this->can('read')) { \Airship\redirect($this->airship_cabin_prefix); } try { $version = $this->pg->getPageVersionByUniqueId($uniqueId); if (!empty($version['metadata'])) { $version['metadata'] = \json_decode($version['metadata'], true); } $page = $this->pg->getPageById($version['page']); } catch (CustomPageNotFoundException $ex) { \Airship\redirect($this->airship_cabin_prefix . '/pages/' . \trim($cabin, '/')); } $prevUnique = $this->pg->getPrevVersionUniqueId((int) $version['page'], $version['versionid']); $nextUnique = $this->pg->getNextVersionUniqueId((int) $version['page'], $version['versionid']); $latestId = $this->pg->getLatestVersionId((int) $version['page']); $this->lens('pages/page_history_view', ['cabins' => $cabins, 'pageinfo' => $page, 'version' => $version, 'latestId' => $latestId, 'prev_url' => $prevUnique, 'next_url' => $nextUnique, 'dir' => $path, 'cabin' => $cabin, 'pathinfo' => \Airship\chunk($path)]); }
/** * Get the parent directory * * @param string $dir * @param string $cabin * @return int */ public function getParentDirFromStr(string $dir, string $cabin = '') : int { return $this->getParentDir(\Airship\chunk($dir), $cabin); }