/**
  * 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;
 }
Example #2
0
 /**
  * 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);
     }
 }
Example #3
0
/**
 * 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;
}
Example #4
0
 /**
  * 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();
 }
Example #5
0
 /**
  * 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];
 }
Example #6
0
 /**
  * @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', '?'));
 }
Example #7
0
 /**
  * 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)]);
 }
Example #8
0
 /**
  * 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);
 }