/** * @param string $input * @return string * @throws \TypeError */ public static function nonEmpty(string $input) : string { if (Util::stringLength($input) < 1) { throw new \TypeError(); } return $input; }
/** * @covers Util::downloadFileType() */ public function testDownloadFileType() { $vectors = [['in' => 'text/javascript', 'out' => 'text/plain'], ['in' => 'image/png', 'out' => 'image/png'], ['in' => 'application/javascript', 'out' => 'text/plain'], ['in' => 'text/html', 'out' => 'text/plain'], ['in' => 'text/html; charset=UTF-8', 'out' => 'text/plain; charset=UTF-8']]; foreach ($vectors as $test) { $this->assertSame($test['out'], Util::downloadFileType($test['in'])); } }
/** * @route my/files/{string}/info * @param string $cabin */ public function getFileInfo(string $cabin = '') { $this->files->ensureDirExists($this->root_dir, $cabin); $dir = $this->determinePath($cabin); if (empty($_GET['file'])) { \Airship\redirect($this->airship_cabin_prefix . '/my_files/' . \urlencode($cabin), ['dir' => $dir]); } if (!\in_array($cabin, $this->getCabinNamespaces())) { \Airship\redirect($this->airship_cabin_prefix); } $this->storeLensVar('title', \__('%s', 'default', Util::noHTML(!empty($dir) ? $dir . '/' . $_GET['file'] : $_GET['file']))); $this->commonGetFileInfo($_GET['file'], $dir, $cabin); }
/** * @param string $cabinName * @route gadgets/cabin/{string} */ public function manageForCabin(string $cabinName = '') { $cabins = $this->getCabinNamespaces(); if (!\in_array($cabinName, $cabins)) { \Airship\redirect($this->airship_cabin_prefix . '/gadgets'); } if (!$this->can('update')) { \Airship\redirect($this->airship_cabin_prefix . '/gadgets'); } $gadgets = \Airship\loadJSON(ROOT . '/Cabin/' . $cabinName . '/config/gadgets.json'); $post = $this->post(GadgetsFilter::fromConfig(\array_keys($gadgets))); if ($post) { if ($this->updateCabinGadgets($gadgets, $post, $cabinName)) { \Airship\clear_cache(); \Airship\redirect($this->airship_cabin_prefix . '/gadgets/cabin/' . $cabinName); } } $this->lens('gadget_manage', ['cabins' => $cabins, 'gadgets' => $gadgets, 'title' => \__('Gadgets for %s', 'default', Util::noHTML($cabinName))]); }
/** * View a version of a blog post. * * @param string $postID * @param string $uniqueID * * @route blog/post/history/{id}/view/{string} */ public function postHistoryView(string $postID = '', string $uniqueID = '') { $postID = (int) $postID; $blog = $this->blog->getBlogPostById($postID); if (!$blog || !$this->can('read')) { \Airship\redirect($this->airship_cabin_prefix . '/blog/post'); } $blog['tags'] = $this->blog->getTagsForPost($postID); $version = $this->blog->getBlogPostVersionByUniqueId($uniqueID); if ((int) $version['postid'] !== $postID || empty($version)) { \Airship\redirect($this->airship_cabin_prefix . '/blog/post/history/' . $postID); } if ($this->isSuperUser()) { $authors = $this->author->getAll(); } else { $authors = $this->author->getForUser($this->getActiveUserId()); } $categories = $this->blog->getCategoryTree(); $tags = $this->blog->getTags(); $this->lens('blog/post_history_view', ['active_link' => 'bridge-link-blog-posts', 'authors' => $authors, 'blogpost' => $blog, 'categories' => $categories, 'tags' => $tags, 'title' => \__('Revision for Blog Post "%s"', 'default', Util::noHTML($blog['title'])), 'prev_uniqueid' => $this->blog->getPrevVersionUniqueId($postID, (int) $version['versionid']), 'next_uniqueid' => $this->blog->getNextVersionUniqueId($postID, (int) $version['versionid']), 'version' => $version]); }
/** * @param string $mimeHeader * @return bool */ protected function isViewable(string $mimeHeader) : bool { $pos = \strpos($mimeHeader, ';'); if ($pos !== false) { $mimeHeader = Util::subString($mimeHeader, 0, $pos); } return \in_array($mimeHeader, $this->viewableMimeTypes); }
/** * @route motifs/{string} * * @param string $cabinName */ public function manage(string $cabinName = '') { $cabins = $this->getCabinNamespaces(); if (!\in_array($cabinName, $cabins)) { \Airship\redirect($this->airship_cabin_prefix . '/motifs'); } if (!$this->can('update')) { \Airship\redirect($this->airship_cabin_prefix . '/motifs'); } $motifs = \Airship\loadJSON(ROOT . '/Cabin/' . $cabinName . '/config/motifs.json'); $post = $this->post(MotifsFilter::fromConfig(\array_keys($motifs))); if ($post) { if ($this->updateMotifs($motifs, $post, $cabinName)) { \Airship\clear_cache(); \Airship\redirect($this->airship_cabin_prefix . '/motifs/cabin/' . $cabinName); } } $this->lens('motif_manage', ['cabin_name' => $cabinName, 'cabins' => $cabins, 'motifs' => $motifs, 'title' => \__('Motifs for %s', 'default', Util::noHTML($cabinName))]); }
/** * Loads all the necessary information for this author * * @param int $authorId */ protected function loadAuthorInfo(int $authorId) { $this->authorId = $authorId; $this->authorName = $this->author->getName($authorId); $this->authorSlug = $this->author->getSlug($authorId); $this->storeLensVar('header', \__('Files for Author "%s"', 'default', Util::noHTML($this->authorName))); $this->storeLensVar('title', \__('Files for Author "%s"', 'default', Util::noHTML($this->authorName))); $this->root_dir = 'author/' . $this->authorSlug; $this->path_middle = 'author/files/' . $authorId; $this->storeLensVar('path_middle', $this->path_middle); $userId = $this->getActiveUserId(); $this->attribution = ['author' => $authorId, 'uploaded_by' => $userId]; }
/** * Flatten an array into a DSN string and driver * * @param array $dbConf * @param string $username * @param string $password * @return array [$dsn, $driver] * @throws DBAlert\DBException */ public static function flattenDSN(array $dbConf, string $username = '', string $password = '') : array { switch ($dbConf['driver']) { case 'mysql': $dsn = $dbConf['driver'] . ':'; if (Util::subString($dbConf['host'], 0, 5) === 'unix:') { $dsn .= 'unix_socket=' . Util::subString($dbConf['host'], 5) . ';'; } else { $dsn .= 'host=' . $dbConf['host'] . ';'; } if (!empty($dbConf['port'])) { $dsn .= 'port=' . $dbConf['port'] . ';'; } $dsn .= 'dbname=' . $dbConf['database']; return [$dsn, $dbConf['driver'], $dbConf['username'] ?? $username, $dbConf['password'] ?? $password]; case 'pgsql': $dsn = $dbConf['driver'] . ':'; if (isset($dbConf['host'])) { if (Util::subString($dbConf['host'], 0, 5) === 'unix:') { $dsn .= 'unix_socket=' . Util::subString($dbConf['host'], 5) . ';'; } else { $dsn .= 'host=' . $dbConf['host'] . ';'; } } if (!empty($dbConf['port'])) { $dsn .= 'port=' . $dbConf['port'] . ';'; } $dsn .= 'dbname=' . $dbConf['database']; return [$dsn, $dbConf['driver'], $dbConf['username'] ?? $username, $dbConf['password'] ?? $password]; case 'sqlite': $dsn = $dbConf['driver'] . ':'; if (isset($dbConf['path'])) { $dsn .= $dbConf['path']; } else { $dsn .= ':memory:'; } return [$dsn, $dbConf['driver'], null, null]; default: throw new DBAlert\DBException(\trk('errors.database.not_implemented', (string) $dbConf['driver'])); } }
/** * Process data using the filter rules. * * @param mixed $data * @return mixed * @throws \TypeError */ public function process($data = null) { if ($this->type === 'string') { if (\is_array($data)) { throw new \TypeError(\sprintf('Unexpected array for string filter (%s).', $this->index)); } if (\is_string($data)) { } elseif (\is_object($data) && \method_exists($data, '__toString')) { $data = (string) $data; } elseif (\is_numeric($data)) { $data = (string) $data; } elseif (\is_null($data)) { $data = null; } else { throw new \TypeError(\sprintf('Expected a string (%s).', $this->index)); } } if ($this->type === 'int') { if (\is_array($data)) { throw new \TypeError(\sprintf('Unexpected array for integer filter (%s).', $this->index)); } if (\is_int($data) || \is_float($data)) { $data = (int) $data; } elseif (\is_null($data) || $data === '') { $data = null; } elseif (\is_string($data) && \preg_match('#^\\-?[0-9]+$#', $data)) { $data = (int) $data; } else { throw new \TypeError(\sprintf('Expected an integer (%s).', $this->index)); } } if ($this->type === 'float') { if (\is_array($data)) { throw new \TypeError(\sprintf('Unexpected array for float filter (%s).', $this->index)); } if (\is_int($data) || \is_float($data)) { $data = (double) $data; } elseif (\is_null($data) || $data === '') { $data = null; } elseif (\is_string($data) && \is_numeric($data)) { $data = (double) $data; } else { throw new \TypeError(\sprintf('Expected an integer or floating point number (%s).', $this->index)); } } if ($this->type === 'array' || Util::subString($this->type, -2) === '[]') { if (\is_array($data)) { $data = (array) $data; } elseif (\is_null($data)) { $data = []; } else { throw new \TypeError(\sprintf('Expected an array (%s).', $this->index)); } } if ($this->type === 'bool') { if (\is_array($data)) { throw new \TypeError(\sprintf('Unexpected array for boolean filter (%s).', $this->index)); } $data = !empty($data); } $data = $this->applyCallbacks($data, 0); if ($data === null) { $data = $this->default; } // For type strictness: switch ($this->type) { case 'bool': return (bool) $data; case 'float': return (double) $data; case 'int': return (int) $data; case 'string': return (string) $data; default: return $data; } }
/** * Generate, store, and return the index and token * * @param string $lockTo What URI endpoint this is valid for * @return array [string, string] */ protected function generateToken(string $lockTo = '') : array { // Create a distinct index: do { $index = Base64UrlSafe::encode(\random_bytes(18)); } while (isset($_SESSION[$this->sessionIndex][$index])); $token = Base64UrlSafe::encode(\random_bytes(33)); $_SESSION[$this->sessionIndex][$index] = ['created' => \intval(\date('YmdHis')), 'uri' => isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : $_SERVER['SCRIPT_NAME'], 'token' => $token]; if (!empty($lockTo)) { // Get rid of trailing slashes. if (\preg_match('#/$#', $lockTo)) { $lockTo = Util::subString($lockTo, 0, Util::stringLength($lockTo) - 1); } $_SESSION[$this->sessionIndex][$index]['lockto'] = $lockTo; } $this->recycleTokens(); return [$index, $token]; }
$extensions = \array_slice($argv, 1); } else { $extensions = ['php', 'twig']; } $fileList = []; $repository = 'https://github.com/paragonie/airship/blob/master/'; $cutoff = \strlen(\dirname(__DIR__) . '/src') + 1; $dirs = []; $allDirs = \Airship\list_all_files(\dirname(__DIR__) . '/src'); \sort($allDirs, \SORT_STRING & ~\SORT_FLAG_CASE); foreach ($allDirs as $file) { $print = \trim(Util::subString($file, $cutoff), '/'); $pieces = \explode('/', $print); $max = \count($pieces) - 1; $name = \array_pop($pieces); if (Util::subString($print, 0, 3) === 'tmp' || Util::subString($print, 0, 5) === 'files') { continue; } $currentDir = \implode('/', $pieces); if ($max > 0 && !isset($dirs[$currentDir])) { echo \str_repeat(' ', 3 * ($max - 1)) . '- [ ] '; echo $pieces[$max - 1]; $dirs[$currentDir] = true; echo "\n"; } if (\preg_match('/\\.([^.]+)$/', $name, $m)) { if (!\in_array($m[1], $extensions)) { continue; } } else { continue;
/** * List all of the blog posts for a given year * @param string $year * @route blog/{year} */ public function listYear(string $year) { list($offset, $limit) = $this->getOffsetAndLimit(); $count = $this->blog->countByYear($year); $blogRoll = $this->blog->listByYear($year, $limit, $offset); $mathJAX = false; foreach ($blogRoll as $i => $blog) { $blogRoll[$i] = $this->blog->getSnippet($blog); if (Binary::safeStrlen($blogRoll[$i]['snippet']) !== Binary::safeStrlen($blog['body'])) { $blogRoll[$i]['snippet'] = \rtrim($blogRoll[$i]['snippet'], "\n"); } $mathJAX = $mathJAX || \strpos($blog['body'], '$$') !== false; } $dt = new \DateTime("{$year}-01-01"); $page = (int) \ceil($offset / ($limit ?? 1)) + 1; $args = ['blogroll' => $blogRoll, 'mathjax' => $mathJAX, 'pageTitle' => \__('Blog Posts in the Year %s (Page %d)', 'default', Util::noHTML($dt->format('Y')), $page), 'pagination' => ['base' => \Airship\LensFunctions\cabin_url() . 'blog/' . $year, 'suffix' => '/?page=', 'count' => $count, 'page' => $page, 'per_page' => $limit]]; $this->config('blog.cachelists') ? $this->stasis('blog/list', $args) : $this->lens('blog/list', $args); }