diff --git a/Crawler.php b/Crawler.php
new file mode 100644
index 0000000..8fb777e
--- /dev/null
+++ b/Crawler.php
@@ -0,0 +1,192 @@
+ext = explode(',', $extensions);
+ $this->ext = array_map('trim', $this->ext);
+ $this->ext = array_map('preg_quote_cb', $this->ext);
+ $this->ext = implode('|', $this->ext);
+ }
+
+ public function setSortBy($sortby)
+ {
+ $this->sortby = $sortby;
+ }
+
+ public function setSortReverse($sortreverse)
+ {
+ $this->sortreverse = $sortreverse;
+ }
+
+ /**
+ * Does a (recursive) crawl for finding files based on a given pattern.
+ * Based on a safe glob reimplementation using fnmatch and opendir.
+ *
+ * @param string $path the path to search in
+ * @param string $pattern the pattern to match to
+ * @param bool $recursive whether to search recursively
+ * @param string $titlefile the name of the title file
+ * @return array a hierarchical filelist or false if nothing could be found
+ *
+ * @see http://www.php.net/manual/en/function.glob.php#71083
+ */
+ public function crawl($root, $local, $pattern, $recursive, $titlefile)
+ {
+ $path = $root . $local;
+
+ if (($dir = opendir($path)) === false) return [];
+ $result = [];
+ while (($file = readdir($dir)) !== false) {
+ if ($file[0] == '.' || $file == $titlefile) {
+ // ignore hidden, system and title files
+ continue;
+ }
+ $self = $local . '/' . $file;
+ $filepath = $path . '/' . $file;
+ if (!is_readable($filepath)) continue;
+
+ if ($this->fnmatch($pattern, $file) || (is_dir($filepath) && $recursive)) {
+ if (!is_dir($filepath) && !$this->isExtensionAllowed($file)) {
+ continue;
+ }
+
+ // get title file
+ $filename = $file;
+ if (is_dir($filepath)) {
+ $title = $filepath . '/' . $titlefile;
+ if (is_readable($title)) {
+ $filename = io_readFile($title, false);
+ }
+ }
+
+ // prepare entry
+ if (!is_dir($filepath) || $recursive) {
+ $entry = [
+ 'name' => $filename,
+ 'local' => $self,
+ 'path' => $filepath,
+ 'mtime' => filemtime($filepath),
+ 'ctime' => filectime($filepath),
+ 'size' => filesize($filepath),
+ 'children' => ((is_dir($filepath) && $recursive) ?
+ $this->crawl($root, $self, $pattern, $recursive, $titlefile) :
+ false
+ ),
+ 'treesize' => 0,
+ ];
+
+ // calculate tree size
+ if ($entry['children'] !== false) {
+ foreach ($entry['children'] as $child) {
+ $entry['treesize'] += $child['treesize'];
+ }
+ } else {
+ $entry['treesize'] = 1;
+ }
+
+ // add entry to result
+ $result[] = $entry;
+ }
+ }
+ }
+ closedir($dir);
+ return $this->sortItems($result);
+ }
+
+ /**
+ * Sort the given items by the current sortby and sortreverse settings
+ *
+ * @param array $items
+ * @return array
+ */
+ protected function sortItems($items)
+ {
+ $callback = [$this, 'compare' . ucfirst($this->sortby)];
+ if (!is_callable($callback)) return $items;
+
+ usort($items, $callback);
+ if ($this->sortreverse) {
+ $items = array_reverse($items);
+ }
+ return $items;
+ }
+
+ /**
+ * Check if a file is allowed by the configured extensions
+ *
+ * @param string $file
+ * @return bool
+ */
+ protected function isExtensionAllowed($file)
+ {
+ if ($this->ext === '') return true; // no restriction
+ return preg_match('/(' . $this->ext . ')$/i', $file);
+ }
+
+
+ /**
+ * Replacement for fnmatch() for windows systems.
+ *
+ * @author jk at ricochetsolutions dot com
+ * @link http://www.php.net/manual/en/function.fnmatch.php#71725
+ */
+ protected function fnmatch($pattern, $string)
+ {
+ return preg_match(
+ "#^" . strtr(
+ preg_quote($pattern, '#'),
+ [
+ '\*' => '.*',
+ '\?' => '.',
+ '\[' => '[',
+ '\]' => ']'
+ ]
+ ) . "$#i",
+ $string
+ );
+ }
+
+ public function compareName($a, $b)
+ {
+ return strcmp($a['name'], $b['name']);
+ }
+
+ public function compareIname($a, $b)
+ {
+ return strcmp(strtolower($a['name']), strtolower($b['name']));
+ }
+
+ public function compareCtime($a, $b)
+ {
+ return $a['ctime'] <=> $b['ctime'];
+ }
+
+ public function compareMtime($a, $b)
+ {
+ return $a['mtime'] <=> $b['mtime'];
+ }
+
+ public function compareSize($a, $b)
+ {
+ return $a['size'] <=> $b['size'];
+ }
+}
diff --git a/Output.php b/Output.php
new file mode 100644
index 0000000..be7b7ae
--- /dev/null
+++ b/Output.php
@@ -0,0 +1,283 @@
+renderer = $renderer;
+ $this->basedir = $basedir;
+ $this->webdir = $webdir;
+ $this->files = $files;
+ }
+
+ public function renderAsList($params)
+ {
+ if ($this->renderer instanceof \Doku_Renderer_xhtml) {
+ $this->renderer->doc .= '
';
+ }
+
+ $this->renderListItems($this->files, $params);
+
+ if ($this->renderer instanceof \Doku_Renderer_xhtml) {
+ $this->renderer->doc .= '
';
+ }
+ }
+
+ /**
+ * Renders the files as a table, including details if configured that way.
+ *
+ * @param array $params the parameters of the filelist call
+ */
+ public function renderAsTable($params)
+ {
+ if ($this->renderer instanceof \Doku_Renderer_xhtml) {
+ $this->renderer->doc .= '';
+ }
+
+ $items = $this->flattenResultTree($this->files);
+ $this->renderTableItems($items, $params);
+
+ if ($this->renderer instanceof \Doku_Renderer_xhtml) {
+ $this->renderer->doc .= '
';
+ }
+ }
+
+
+ /**
+ * Renders the files as a table, including details if configured that way.
+ *
+ * @param array $params the parameters of the filelist call
+ */
+ protected function renderTableItems($items, $params)
+ {
+
+ $renderer = $this->renderer;
+
+
+ // count the columns
+ $columns = 1;
+ if ($params['showsize']) {
+ $columns++;
+ }
+ if ($params['showdate']) {
+ $columns++;
+ }
+
+ $renderer->table_open($columns);
+
+ if ($params['tableheader']) {
+ $renderer->tablethead_open();
+ $renderer->tablerow_open();
+
+ $renderer->tableheader_open();
+ $renderer->cdata($this->getLang('filename'));
+ $renderer->tableheader_close();
+
+ if ($params['showsize']) {
+ $renderer->tableheader_open();
+ $renderer->cdata($this->getLang('filesize'));
+ $renderer->tableheader_close();
+ }
+
+ if ($params['showdate']) {
+ $renderer->tableheader_open();
+ $renderer->cdata($this->getLang('lastmodified'));
+ $renderer->tableheader_close();
+ }
+
+ $renderer->tablerow_close();
+ $renderer->tablethead_close();
+ }
+
+ $renderer->tabletbody_open();
+ foreach ($items as $item) {
+ $renderer->tablerow_open();
+ $renderer->tablecell_open();
+ $this->renderItemLink($item, $params['randlinks']);
+ $renderer->tablecell_close();
+
+ if ($params['showsize']) {
+ $renderer->tablecell_open(1, 'right');
+ $renderer->cdata(filesize_h($item['size']));
+ $renderer->tablecell_close();
+ }
+
+ if ($params['showdate']) {
+ $renderer->tablecell_open();
+ $renderer->cdata(dformat($item['mtime']));
+ $renderer->tablecell_close();
+ }
+
+ $renderer->tablerow_close();
+ }
+ $renderer->tabletbody_close();
+ $renderer->table_close();
+ }
+
+
+ /**
+ * Recursively renders a tree of files as list items.
+ *
+ * @param array $items the files to render
+ * @param array $params the parameters of the filelist call
+ * @param int $level the level to render
+ * @return void
+ */
+ protected function renderListItems($items, $params, $level = 1)
+ {
+ if ($params['style'] == 'olist') {
+ $this->renderer->listo_open();
+ } else {
+ $this->renderer->listu_open();
+ }
+
+ foreach ($items as $file) {
+ if ($file['children'] === false && $file['treesize'] === 0) continue; // empty directory
+
+ $this->renderer->listitem_open($level);
+ $this->renderer->listcontent_open();
+
+ if ($file['children'] !== false && $file['treesize'] > 0) {
+ // render the directory and its subtree
+ $this->renderer->cdata($file['name']);
+ $this->renderListItems($file['children'], $params, $level + 1);
+ } elseif ($file['children'] === false) {
+ // render the file link
+ $this->renderItemLink($file, $params['randlinks']);
+
+ // render filesize
+ if ($params['showsize']) {
+ $this->renderer->cdata($params['listsep'] . filesize_h($file['size']));
+ }
+ // render lastmodified
+ if ($params['showdate']) {
+ $this->renderer->cdata($params['listsep'] . dformat($file['mtime']));
+ }
+ }
+
+ $this->renderer->listcontent_close();
+ $this->renderer->listitem_close();
+ }
+
+ if ($params['style'] == 'olist') {
+ $this->renderer->listo_close();
+ } else {
+ $this->renderer->listu_close();
+ }
+ }
+
+ protected function renderItemLink($item, $cachebuster = false)
+ {
+ if ($this->renderer instanceof \Doku_Renderer_xhtml) {
+ $this->renderItemLinkXHTML($item, $cachebuster);
+ } else {
+ $this->renderItemLinkAny($item, $cachebuster);
+ }
+ }
+
+ /**
+ * Render a file link on the XHTML renderer
+ */
+ protected function renderItemLinkXHTML($item, $cachebuster = false)
+ {
+ global $conf;
+ /** @var \Doku_Renderer_xhtml $renderer */
+ $renderer = $this->renderer;
+
+ //prepare for formating
+ $link['target'] = $conf['target']['extern'];
+ $link['style'] = '';
+ $link['pre'] = '';
+ $link['suf'] = '';
+ $link['more'] = '';
+ $link['url'] = $this->itemWebUrl($item, $cachebuster);
+ $link['name'] = $item['name'];
+ $link['title'] = $renderer->_xmlEntities($link['url']);
+ if ($conf['relnofollow']) $link['more'] .= ' rel="nofollow"';
+ [$ext,] = mimetype(basename($item['local']));
+ $link['class'] .= ' mediafile mf_' . $ext;
+ $renderer->doc .= $renderer->_formatLink($link);
+ }
+
+ /**
+ * Render a file link on any Renderer
+ * @param array $item
+ * @param bool $cachebuster
+ * @return void
+ */
+ protected function renderItemLinkAny($item, $cachebuster = false)
+ {
+ $this->renderer->externalmedialink($this->itemWebUrl($item, $cachebuster), $item['name']);
+ }
+
+ /**
+ * Construct the Web URL for a given item
+ *
+ * @param array $item The item data as returned by the Crawler
+ * @param bool $cachbuster add a cachebuster to the URL?
+ * @return string
+ */
+ protected function itemWebUrl($item, $cachbuster = false)
+ {
+ if (str_ends_with($this->webdir, '=')) {
+ $url = $this->webdir . rawurlencode($item['local']);
+ } else {
+ $url = $this->webdir . $item['local'];
+ }
+
+ if ($cachbuster) {
+ if (strpos($url, '?') === false) {
+ $url .= '?t=' . $item['mtime'];
+ } else {
+ $url .= '&t=' . $item['mtime'];
+ }
+ }
+ return $url;
+ }
+
+ /**
+ * Flattens the filelist by recursively walking through all subtrees and
+ * merging them with a prefix attached to the filenames.
+ *
+ * @param array $items the tree to flatten
+ * @param string $prefix the prefix to attach to all processed nodes
+ * @return array a flattened representation of the tree
+ */
+ protected function flattenResultTree($items, $prefix = '')
+ {
+ $result = [];
+ foreach ($items as $file) {
+ if ($file['children'] !== false) {
+ $result = array_merge(
+ $result,
+ $this->flattenResultTree($file['children'], $prefix . $file['name'] . '/')
+ );
+ } else {
+ $file['name'] = $prefix . $file['name'];
+ $result[] = $file;
+ }
+ }
+ return $result;
+ }
+
+ protected function getLang($key)
+ {
+ $syntax = plugin_load('syntax', 'filelist');
+ return $syntax->getLang($key);
+ }
+}
diff --git a/Path.php b/Path.php
new file mode 100644
index 0000000..479c8a2
--- /dev/null
+++ b/Path.php
@@ -0,0 +1,144 @@
+paths = $this->parsePathConfig($pathConfig);
+ }
+
+ /**
+ * Parse the path configuration into an internal array
+ *
+ * roots (and aliases) are always saved with a trailing slash
+ *
+ * @return array
+ */
+ protected function parsePathConfig($pathConfig)
+ {
+ $paths = [];
+ $lines = explode("\n", $pathConfig);
+ $lastRoot = '';
+ foreach ($lines as $line) {
+ $line = trim($line);
+ if (empty($line)) {
+ continue;
+ }
+
+ if (str_starts_with($line, 'A>')) {
+ // this is an alias for the last read root
+ $line = trim(substr($line, 2));
+ if (!isset($paths[$lastRoot])) continue; // no last root, no alias
+ $alias = $this->cleanPath($line);
+ $paths[$lastRoot]['alias'] = $alias;
+ $paths[$alias] = &$paths[$lastRoot]; // alias references the original
+ } elseif (str_starts_with($line, 'W>')) {
+ // this is a web path for the last read root
+ $line = trim(substr($line, 2));
+ if (!isset($paths[$lastRoot])) continue; // no last path, no web path
+ $paths[$lastRoot]['web'] = $line;
+ } else {
+ // this is a new path
+ $line = $this->cleanPath($line);
+ $lastRoot = $line;
+ $paths[$line] = [
+ 'root' => $line,
+ 'web' => DOKU_BASE . 'lib/plugins/filelist/file.php?root=' . rawurlencode($line).'&file=',
+ ];
+ }
+ }
+
+ return $paths;
+ }
+
+ /**
+ * Check if a given path is listable and return it's configuration
+ *
+ * @param string $path
+ * @param bool $addTrailingSlash
+ * @return array
+ * @throws \Exception if the given path is not allowed
+ */
+ public function getPathInfo($path, $addTrailingSlash = true)
+ {
+ $path = $this->cleanPath($path, $addTrailingSlash);
+
+ $paths = $this->paths;
+ $allowed = array_keys($paths);
+ usort($allowed, function ($a, $b) {
+ return strlen($a) - strlen($b);
+ });
+ $allowed = array_map('preg_quote_cb', $allowed);
+ $regex = '/^(' . implode('|', $allowed) . ')/';
+
+ if (!preg_match($regex, $path, $matches)) {
+ throw new \Exception('Path not allowed: ' . $path);
+ }
+ $match = $matches[1];
+
+ $pathInfo = $paths[$match];
+ $pathInfo['local'] = substr($path, strlen($match));
+ $pathInfo['path'] = $pathInfo['root'] . $pathInfo['local'];
+
+
+ return $pathInfo;
+ }
+
+ /**
+ * Clean a path for better comparison
+ *
+ * Converts all backslashes to forward slashes
+ * Keeps leading double backslashes for UNC paths
+ * Ensure a single trailing slash unless disabled
+ *
+ * @param string $path
+ * @return string
+ */
+ public static function cleanPath($path, $addTrailingSlash = true)
+ {
+ if (str_starts_with($path, '\\\\')) {
+ $unc = '\\\\';
+ } else {
+ $unc = '';
+ }
+ $path = ltrim($path, '\\');
+ $path = str_replace('\\', '/', $path);
+ $path = self::realpath($path);
+ if ($addTrailingSlash) {
+ $path = rtrim($path, '/');
+ $path .= '/';
+ }
+
+ return $unc . $path;
+ }
+
+ /**
+ * Canonicalizes a given path. A bit like realpath, but without the resolving of symlinks.
+ *
+ * @author anonymous
+ * @see
+ */
+ public static function realpath($path)
+ {
+ $path = explode('/', $path);
+ $output = [];
+ $counter = count($path);
+ for ($i = 0; $i < $counter; $i++) {
+ if ('.' == $path[$i]) continue;
+ if ('' === $path[$i] && $i > 0) continue;
+ if ('..' == $path[$i] && '..' != $output[count($output) - 1]) {
+ array_pop($output);
+ continue;
+ }
+ $output[] = $path[$i];
+ }
+ return implode('/', $output);
+ }
+}
diff --git a/conf/default.php b/conf/default.php
index c5a2daa..9568f60 100644
--- a/conf/default.php
+++ b/conf/default.php
@@ -4,6 +4,8 @@
* Options for the filelist plugin
*/
+$conf['paths'] = '';
+
$conf['allow_in_comments'] = 0;
$conf['allowed_absolute_paths'] = DOKU_INC;
$conf['web_paths'] = DOKU_URL;
diff --git a/conf/metadata.php b/conf/metadata.php
index 3e1078f..4ae4b38 100644
--- a/conf/metadata.php
+++ b/conf/metadata.php
@@ -7,6 +7,8 @@
* @author Gina Haeussge
*/
+$meta['paths'] = array('');
+
$meta['allow_in_comments'] = array('onoff');
$meta['allowed_absolute_paths'] = array('');
$meta['web_paths'] = array('');
diff --git a/file.php b/file.php
new file mode 100644
index 0000000..e89049b
--- /dev/null
+++ b/file.php
@@ -0,0 +1,40 @@
+getConf('paths'));
+$path = $INPUT->str('root') . $INPUT->str('file');
+
+try {
+ $pathInfo = $pathUtil->getPathInfo($path, false);
+ if (!is_readable($pathInfo['path'])) {
+ header('Content-Type: text/plain');
+ http_status(404);
+ echo 'Path not readable: ' . $pathInfo['path'];
+ exit;
+ }
+ [$ext, $mime, $download] = mimetype($pathInfo['path'], false);
+ $basename = basename($pathInfo['path']);
+ header('Content-Type: ' . $mime);
+ if ($download) {
+ header('Content-Disposition: attachment; filename="' . $basename . '"');
+ }
+ http_sendfile($pathInfo['path']);
+ readfile($pathInfo['path']);
+} catch (Exception $e) {
+ header('Content-Type: text/plain');
+ http_status(403);
+ echo $e->getMessage();
+ exit;
+}
+
diff --git a/syntax.php b/syntax.php
index 7c26d3d..4138dcf 100644
--- a/syntax.php
+++ b/syntax.php
@@ -1,6 +1,9 @@
*/
-
-define('DOKU_PLUGIN_FILELIST_NOMATCH', -1);
-define('DOKU_PLUGIN_FILELIST_OUTSIDEJAIL', -2);
-
-/**
- * All DokuWiki plugins to extend the parser/rendering mechanism
- * need to inherit from this class
- */
class syntax_plugin_filelist extends SyntaxPlugin
{
- public $mediadir;
- public $is_odt_export = false;
-
- public function __construct()
- {
- global $conf;
- $mediadir = $conf['mediadir'];
- if (!$this->_path_is_absolute($mediadir)) {
- $mediadir = DOKU_INC . '/' . $mediadir;
- }
- $this->mediadir = $this->_win_path_convert($this->_realpath($mediadir) . '/');
- }
-
+ /** @inheritdoc */
public function getType()
{
return 'substition';
}
+ /** @inheritdoc */
public function getPType()
{
return 'block';
}
+ /** @inheritdoc */
public function getSort()
{
return 222;
}
+ /** @inheritdoc */
public function connectTo($mode)
{
- $this->Lexer->addSpecialPattern('\{\{filename>.+?\}\}', $mode, 'plugin_filelist');
$this->Lexer->addSpecialPattern('\{\{filelist>.+?\}\}', $mode, 'plugin_filelist');
}
- /**
- * Handle the match
- */
+ /** @inheritdoc */
public function handle($match, $state, $pos, Doku_Handler $handler)
{
+ global $INPUT;
- // do not allow the syntax in comments
- if (!$this->getConf('allow_in_comments') && isset($_REQUEST['comment']))
+ // do not allow the syntax in discussion plugin comments
+ if (!$this->getConf('allow_in_comments') && $INPUT->has('comment')) {
return false;
-
- $match = substr($match, 2, -2);
- [$type, $match] = explode('>', $match, 2);
- [$pattern, $flags] = explode('&', $match, 2);
-
- if ($type == 'filename') {
- if (strpos($flags, '|') !== false) {
- [$flags, $title] = explode('\|', $flags);
- } else {
- $title = '';
- }
}
+ $match = substr($match, strlen('{{filelist>'), -2);
+ [$path, $flags] = explode('&', $match, 2);
+
// load default config options
$flags = $this->getConf('defaults') . '&' . $flags;
-
$flags = explode('&', $flags);
- $params = ['sort' => 'name', 'order' => 'asc', 'index' => 0, 'limit' => 0, 'offset' => 0, 'style' => 'list', 'tableheader' => 0, 'tableshowsize' => 0, 'tableshowdate' => 0, 'direct' => 0, 'recursive' => 0, 'titlefile' => '_title.txt', 'cache' => 0, 'randlinks' => 0, 'preview' => 0, 'previewsize' => 32, 'link' => 2, 'showsize' => 0, 'showdate' => 0, 'showcreator' => 0, 'listsep' => '", "', 'onhover' => 0, 'ftp' => 0];
+ $params = [
+ 'sort' => 'name',
+ 'order' => 'asc',
+ 'index' => 0,
+ 'limit' => 0,
+ 'offset' => 0,
+ 'style' => 'list',
+ 'tableheader' => 0,
+ 'tableshowsize' => 0,
+ 'tableshowdate' => 0,
+ 'direct' => 0,
+ 'recursive' => 0,
+ 'titlefile' => '_title.txt',
+ 'cache' => 0,
+ 'randlinks' => 0,
+ 'preview' => 0,
+ 'previewsize' => 32,
+ 'link' => 2,
+ 'showsize' => 0,
+ 'showdate' => 0,
+ 'showcreator' => 0,
+ 'listsep' => '", "',
+ 'onhover' => 0,
+ 'ftp' => 0
+ ];
foreach ($flags as $flag) {
[$name, $value] = explode('=', $flag);
- $params[trim($name)] = trim($value);
+ $params[trim($name)] = trim(trim($value), '"'); // quotes can be use to keep whitespace
}
- // recursive filelistings are not supported for the filename command
- if ($type == 'filename') {
- $params['recursive'] = 0;
- }
+ // separate path and pattern
+ $path = Path::cleanPath($path, false);
+ $parts = explode('/', $path);
+ $pattern = array_pop($parts);
+ $base = join('/', $parts) . '/';
- // Trim list separator
- $params['listsep'] = trim($params['listsep'], '"');
-
- return [$type, $pattern, $params, $title, $pos];
+ return [$base, $pattern, $params];
}
/**
* Create output
*/
- public function render($mode, Doku_Renderer $renderer, $data)
+ public function render($format, Doku_Renderer $renderer, $data)
{
- global $conf;
+ [$base, $pattern, $params] = $data;
- [$type, $pattern, $params, $title, $pos] = $data;
-
- if ($mode == 'odt') {
- $this->is_odt_export = true;
+ if ($format != 'xhtml' && $format != 'odt') {
+ return false;
}
// disable caching
if ($params['cache'] === 0) {
$renderer->nocache();
}
- if ($mode == 'xhtml' || $mode == 'odt') {
- $result = $this->_create_filelist($pattern, $params);
- if ($type == 'filename') {
- $result = $this->_filter_out_directories($result);
- }
- // if we got nothing back, display a message
- if ($result == DOKU_PLUGIN_FILELIST_NOMATCH) {
- $renderer->cdata('[n/a: ' . $this->getLang('error_nomatch') . ']');
- return true;
- } elseif ($result == DOKU_PLUGIN_FILELIST_OUTSIDEJAIL) {
- $renderer->cdata('[n/a: ' . $this->getLang('error_outsidejail') . ']');
- return true;
- }
- // if limit is set for a filelist, cut out the relevant slice from the files
- if (($type == 'filelist') && ($params['limit'] != 0)) {
- $result['files'] = array_slice($result['files'], $params['offset'], $params['limit']);
- }
-
- switch ($type) {
- case 'filename':
- $filename = $result['files'][$params['index']]['name'];
- $filepath = $result['files'][$params['index']]['path'];
-
- $this->_render_link($filename, $filepath, $result['basedir'], $result['webdir'], $params, $renderer);
- return true;
-
- case 'filelist':
- if (count($result['files']) == 0)
- break;
-
- switch ($params['style']) {
- case 'list':
- case 'olist':
- if (!$this->is_odt_export) {
- $renderer->doc .= '' . DOKU_LF;
- }
- $this->_render_list($result, $params, $renderer);
- if (!$this->is_odt_export) {
- $renderer->doc .= '
' . DOKU_LF;
- }
- break;
-
- case 'table':
- if (!$this->is_odt_export) {
- $renderer->doc .= '' . DOKU_LF;
- }
- $this->_render_table($result, $params, $pos, $renderer);
- if (!$this->is_odt_export) {
- $renderer->doc .= '
' . DOKU_LF;
- }
- break;
-
- case 'page':
- $this->_render_page($result, $params, $renderer);
- break;
- }
- return true;
- }
+ try {
+ $pathHelper = new Path($this->getConf('paths'));
+ $pathInfo = $pathHelper->getPathInfo($base);
+ } catch (Exception $e) {
+ $renderer->cdata('[n/a: ' . $this->getLang('error_outsidejail') . ']');
+ return true;
}
- return false;
+
+ $crawler = new Crawler($this->getConf('extensions'));
+ $crawler->setSortBy($params['sort']);
+ $crawler->setSortReverse($params['order'] === 'desc');
+ $result = $crawler->crawl($pathInfo['root'], $pathInfo['local'], $pattern, $params['recursive'], $params['titlefile']);
+
+ // if we got nothing back, display a message
+ if ($result == []) {
+ $renderer->cdata('[n/a: ' . $this->getLang('error_nomatch') . ']');
+ return true;
+ }
+
+ $output = new Output($renderer, $pathInfo['root'], $pathInfo['web'], $result);
+
+ switch ($params['style']) {
+ case 'list':
+ case 'olist':
+ $output->renderAsList($params);
+ break;
+ case 'table':
+ $output->renderAsTable($params);
+ break;
+
+ }
+ return true;
+
}
- //~~ Render functions
-
- /**
- * Creates the downloadlink for the given filename, based on the given
- * parameters, and adds it to the output of the renderer.
- *
- * @param $filename the name of the file
- * @param $filepath the path of the file
- * @param $basedir the basedir of the file
- * @param $webdir the base URL of the file
- * @param $params the parameters of the filelist command
- * @param $renderer the renderer to use
- * @return void
- */
- public function _render_link($filename, $filepath, $basedir, $webdir, $params, Doku_Renderer $renderer)
- {
- global $conf;
-
- //prepare for formating
- $link['target'] = $conf['target']['extern'];
- $link['style'] = '';
- $link['pre'] = '';
- $link['suf'] = '';
- $link['more'] = '';
- $link['url'] = $this->_get_link_url($filepath, $basedir, $webdir, $params['randlinks'], $params['direct'], $params['ftp']);
-
- $link['name'] = $filename;
- $link['title'] = $renderer->_xmlEntities($link['url']);
- if ($conf['relnofollow']) $link['more'] .= ' rel="nofollow"';
-
- if ($params['link']) {
- switch ($params['link']) {
- case 1:
- // Link without background image
- $link['class'] = 'media';
- break;
- default:
- // Link with background image
- [$ext, $mime] = mimetype(basename($filepath));
- $link['class'] .= ' mediafile mf_' . $ext;
- break;
- }
-
- //output formatted
- if (!$this->is_odt_export) {
- $renderer->doc .= $renderer->_formatLink($link);
- } else {
- $this->render_odt_link($link, $renderer);
- }
- } else {
- // No link, just plain text.
- $renderer->cdata($filename);
- }
- }
-
- /**
- * Renders a link for odt mode.
- *
- * @param $link the link parameters
- * @param $renderer the renderer to use
- * @return void
- */
- protected function render_odt_link($link, Doku_Renderer $renderer)
- {
- if (method_exists($renderer, 'getODTProperties')) {
- $properties = [];
-
- // Get CSS properties for ODT export.
- $renderer->getODTProperties($properties, 'a', $link['class'], null, 'screen');
-
- // Insert image if present for that media class.
- if (empty($properties ['background-image']) === false) {
- $properties ['background-image'] =
- $renderer->replaceURLPrefix($properties ['background-image'], DOKU_INC);
- $renderer->_odtAddImage($properties ['background-image']);
- }
- }
-
- // Render link.
- $renderer->externallink($link['url'], $link['name']);
- }
-
- /**
- * Renders a list.
- *
- * @param $result the filelist to render
- * @param $params the parameters of the filelist call
- * @param $renderer the renderer to use
- * @return void
- */
- public function _render_list($result, $params, Doku_Renderer $renderer)
- {
- $this->_render_list_items($result['files'], $result['basedir'], $result['webdir'], $params, $renderer);
- }
-
- /**
- * Recursively renders a tree of files as list items.
- *
- * @param $files the files to render
- * @param $basedir the basedir to use
- * @param $webdir the webdir to use
- * @param $params the parameters of the filelist call
- * @param $renderer the renderer to use
- * @param $level the level to render
- * @return void
- */
- public function _render_list_items($files, $basedir, $webdir, $params, Doku_Renderer $renderer, $level = 1)
- {
- global $conf;
-
- if ($params['style'] == 'olist') {
- $renderer->listo_open();
- } else {
- $renderer->listu_open();
- }
-
- foreach ($files as $file) {
- if ($file['children'] !== false && $file['treesize'] > 0) {
- // render the directory and its subtree
- $renderer->listitem_open($level);
- if ($this->is_odt_export) {
- $renderer->p_open();
- }
- $renderer->cdata($file['name']);
- $this->_render_list_items($file['children'], $basedir, $webdir, $params, $renderer, $level + 1);
- if ($this->is_odt_export) {
- $renderer->p_close();
- }
- $renderer->listitem_close();
- } elseif ($file['children'] === false) {
- // open list item
- $renderer->listitem_open($level);
- if ($this->is_odt_export) {
- $renderer->p_open();
- }
- // render the preview image
- if ($params['preview']) {
- $this->_render_preview_image($file['path'], $basedir, $webdir, $params, $renderer);
- }
- // render the file link
- $this->_render_link($file['name'], $file['path'], $basedir, $webdir, $params, $renderer);
- // render filesize
- if ($params['showsize']) {
- $renderer->cdata($params['listsep'] . $this->_size_readable($file['size'], 'PiB', 'bi', '%01.1f %s'));
- }
- // render lastmodified
- if ($params['showdate']) {
- $renderer->cdata($params['listsep'] . strftime($conf['dformat'], $file['mtime']));
- }
- // render lastmodified
- if ($params['showcreator']) {
- $renderer->cdata($params['listsep'] . $file['creator']);
- }
- // close list item
- if ($this->is_odt_export) {
- $renderer->p_close();
- }
- $renderer->listitem_close();
- } else {
- // ignore empty directories
- continue;
- }
- }
-
- if ($params['style'] == 'olist') {
- $renderer->listo_close();
- } else {
- $renderer->listu_close();
- }
- }
-
- /**
- * Renders the files as a table, including details if configured that way.
- *
- * @param $result the filelist to render
- * @param $params the parameters of the filelist call
- * @param $renderer the renderer to use
- * @return void
- */
- public function _render_table($result, $params, $pos, Doku_Renderer $renderer)
- {
- global $conf;
-
- if (!$this->is_odt_export) {
- $renderer->table_open(null, null, $pos);
- } else {
- $columns = 1;
- if ($params['tableshowsize'] || $params['showsize']) {
- $columns++;
- }
- if ($params['tableshowdate'] || $params['showdate']) {
- $columns++;
- }
- if ($params['showcreator']) {
- $columns++;
- }
- if ($params['preview']) {
- $columns++;
- }
- $renderer->table_open($columns, null, $pos);
- }
-
- if ($params['tableheader']) {
- if ($this->is_odt_export) {
- $renderer->tablerow_open();
- }
-
- $renderer->tableheader_open();
- $renderer->cdata($this->getLang('filename'));
- $renderer->tableheader_close();
-
- if ($params['tableshowsize'] || $params['showsize']) {
- $renderer->tableheader_open();
- $renderer->cdata($this->getLang('filesize'));
- $renderer->tableheader_close();
- }
-
- if ($params['tableshowdate'] || $params['showdate']) {
- $renderer->tableheader_open();
- $renderer->cdata($this->getLang('lastmodified'));
- $renderer->tableheader_close();
- }
-
- if ($params['showcreator']) {
- $renderer->tableheader_open();
- $renderer->cdata($this->getLang('createdby'));
- $renderer->tableheader_close();
- }
-
- if ($params['preview']) {
- $renderer->tableheader_open(1, 'center', 1);
- switch ($params['preview']) {
- case 1:
- $renderer->cdata($this->getLang('preview') . ' / ' . $this->getLang('filetype'));
- break;
- case 2:
- $renderer->cdata($this->getLang('preview'));
- break;
- case 3:
- $renderer->cdata($this->getLang('filetype'));
- break;
- }
- $renderer->tableheader_close();
- }
-
- if ($this->is_odt_export) {
- $renderer->tablerow_close();
- }
- }
-
- foreach ($result['files'] as $file) {
- $renderer->tablerow_open();
- $renderer->tablecell_open();
- $this->_render_link($file['name'], $file['path'], $result['basedir'], $result['webdir'], $params, $renderer);
- $renderer->tablecell_close();
-
- if ($params['tableshowsize'] || $params['showsize']) {
- $renderer->tablecell_open(1, 'right');
- $renderer->cdata($this->_size_readable($file['size'], 'PiB', 'bi', '%01.1f %s'));
- $renderer->tablecell_close();
- }
-
- if ($params['tableshowdate'] || $params['showdate']) {
- $renderer->tablecell_open();
- $renderer->cdata(strftime($conf['dformat'], $file['mtime']));
- $renderer->tablecell_close();
- }
-
- if ($params['showcreator']) {
- $renderer->tablecell_open();
- $renderer->cdata($file['creator']);
- $renderer->tablecell_close();
- }
-
- if ($params['preview']) {
- $renderer->tablecell_open(1, 'center', 1);
-
- $this->_render_preview_image($file['path'], $result['basedir'], $result['webdir'], $params, $renderer);
- $renderer->tablecell_close();
- }
-
- $renderer->tablerow_close();
- }
- $renderer->table_close($pos);
- }
-
- /**
- * Renders a page.
- *
- * @param $result the filelist to render
- * @param $params the parameters of the filelist call
- * @param $renderer the renderer to use
- * @return void
- */
- public function _render_page($result, $params, Doku_Renderer $renderer)
- {
- if (method_exists($renderer, 'getLastlevel') === false) {
- $class_vars = get_class_vars(get_class($renderer));
- if ($class_vars ['lastlevel'] !== null) {
- // Old releases before "hrun": $lastlevel is accessible
- $lastlevel = $renderer->lastlevel + 1;
- } else {
- // Release "hrun" or newer without method 'getLastlevel()'.
- // Lastlevel can't be determined. Workaroud: always use level 1.
- $lastlevel = 1;
- }
- } else {
- $lastlevel = $renderer->getLastlevel() + 1;
- }
- $this->_render_page_section($result['files'], $result['basedir'], $result['webdir'], $params, $renderer, $lastlevel);
- }
-
- /**
- * Recursively renders a tree of files as page sections using headlines.
- *
- * @param $files the files to render
- * @param $basedir the basedir to use
- * @param $webdir the webdir to use
- * @param $params the parameters of the filelist call
- * @param $renderer the renderer to use
- * @param $level the level to render
- * @return void
- */
- public function _render_page_section($files, $basedir, $webdir, $params, Doku_Renderer $renderer, $level)
- {
- $trees = [];
- $leafs = [];
-
- foreach ($files as $file) {
- if ($file['children'] !== false) {
- if ($file['treesize'] > 0) {
- $trees[] = $file;
- }
- } else {
- $leafs[] = $file;
- }
- }
-
- $this->_render_list_items($leafs, $basedir, $webdir, $params, $renderer);
-
- if ($level < 7) {
- foreach ($trees as $tree) {
- $renderer->header($tree['name'], $level, 0);
- $renderer->section_open($level);
- $this->_render_page_section($tree['children'], $basedir, $webdir, $params, $renderer, $level + 1);
- $renderer->section_close();
- }
- } else {
- $this->_render_list_items($trees, $basedir, $webdir, $params, $renderer);
- }
- }
-
- /**
- * Render a preview item for file $filepath.
- *
- * @param $filepath the file for which a preview image shall be rendered
- * @param $basedir the basedir to use
- * @param $webdir the webdir to use
- * @param $params the parameters of the filelist call
- * @param $renderer the renderer to use
- * @return void
- */
- protected function _render_preview_image($filepath, $basedir, $webdir, $params, Doku_Renderer $renderer)
- {
- $imagepath = $this->get_preview_image_path($filepath, $params, $isImage);
- if (!empty($imagepath)) {
- if ($isImage == false) {
- // Generate link to returned filetype icon
- $imgLink = $this->_get_link_url($imagepath, $basedir, $webdir, 0, 1);
- } else {
- // Generate link to image file
- $imgLink = $this->_get_link_url($filepath, $basedir, $webdir, $params['randlinks'], $params['direct'], $params['ftp']);
- }
-
- $previewsize = $params['previewsize'];
- if ($previewsize == 0) {
- $previewsize = 32;
- }
- $imgclass = '';
- if ($params['onhover']) {
- $imgclass = 'class="filelist_preview"';
- }
-
- if (!$this->is_odt_export) {
- $renderer->doc .= '
';
- } else {
- [$width, $height] = $renderer->_odtGetImageSize($imagepath, $previewsize, $previewsize);
- $renderer->_odtAddImage($imagepath, $width . 'cm', $height . 'cm');
- }
- }
- }
-
- //~~ Filelist functions
-
- /**
- * Creates the filelist based on the given glob-pattern and
- * sorting and ordering parameters.
- *
- * @param $pattern the pattern
- * @param $params the parameters of the filelist command
- * @return a filelist data structure containing the found files and base-
- * and webdir
- */
- public function _create_filelist($pattern, $params)
- {
- global $conf;
- global $ID;
-
- $allowed_absolute_paths = explode(',', $this->getConf('allowed_absolute_paths'));
-
- $result = ['files' => [], 'basedir' => false, 'webdir' => false];
-
- // we don't want to use $conf['media'] here as that path has symlinks resolved
- if (!$params['direct']) {
- // if media path is not absolute, precede it with the current namespace
- if ($pattern[0] != ':') {
- $pattern = ':' . getNS($ID) . ':' . $pattern;
- }
- // replace : with / and prepend mediadir
- $pattern = $this->mediadir . str_replace(':', '/', $pattern);
- } elseif ($params['direct'] == 2) {
- // treat path as relative to first configured path
- $pattern = $allowed_absolute_paths[0] . '/' . $pattern;
- } elseif (!$this->_path_is_absolute($pattern)) {
- // if path is not absolute, precede it with DOKU_INC
- $pattern = DOKU_INC . $pattern;
- }
- // get the canonicalized basedir (without resolving symlinks)
- $dir = $this->_realpath($this->_win_path_convert(dirname($pattern))) . '/';
-
- // if the directory does not exist, we of course have no matches
- if (!$dir || !file_exists($dir)) {
- return DOKU_PLUGIN_FILELIST_NOMATCH;
- }
-
- // match pattern aginst allowed paths
- $web_paths = explode(',', $this->getConf('web_paths'));
- $basedir = false;
- $webdir = false;
- if (count($allowed_absolute_paths) === count($web_paths)) {
- $counter = count($allowed_absolute_paths);
- for ($i = 0; $i < $counter; $i++) {
- $abs_path = $this->_win_path_convert(trim($allowed_absolute_paths[$i]));
- if (strstr($dir, (string) $abs_path) == $dir) {
- $basedir = $abs_path;
- $webdir = trim($web_paths[$i]);
- break;
- }
- }
- }
-
- // $basedir is false if $dir was not in one of the allowed paths
- if ($basedir === false) {
- return DOKU_PLUGIN_FILELIST_OUTSIDEJAIL;
- }
-
- // retrieve fileinformation
- $result['basedir'] = $basedir;
- $result['webdir'] = $webdir;
- $result['files'] = $this->_crawl_files($this->_win_path_convert($pattern), $params);
- if (!$result['files']) {
- return DOKU_PLUGIN_FILELIST_NOMATCH;
- }
-
- // flatten filelist if the displaymode is table
- if ($params['style'] == 'table') {
- $result['files'] = $this->_flatten_filelist($result['files']);
- }
-
- // sort the list
- $callback = false;
- $reverseflag = false;
- if ($params['sort'] == 'mtime') {
- $callback = [$this, '_compare_mtimes'];
- if ($params['order'] == 'asc') $reverseflag = true;
- } elseif ($params['sort'] == 'ctime') {
- $callback = [$this, '_compare_ctimes'];
- if ($params['order'] == 'asc') $reverseflag = true;
- } elseif ($params['sort'] == 'size') {
- $callback = [$this, '_compare_sizes'];
- if ($params['order'] == 'desc') $reverseflag = true;
- } elseif ($params['sort'] == 'iname') {
- $callback = [$this, '_compare_inames'];
- if ($params['order'] == 'desc') $reverseflag = true;
- } else {
- $callback = [$this, '_compare_names'];
- if ($params['order'] == 'desc') $reverseflag = true;
- }
- $this->_sort_filelist($result['files'], $callback, $reverseflag);
-
- // return the list
- if (count($result['files']) > 0)
- return $result;
- else return DOKU_PLUGIN_FILELIST_NOMATCH;
- }
-
- /**
- * Recursively sorts the given tree using the given callback. Optionally
- * reverses the sorted tree before returning it.
- *
- * @param $files the files to sort
- * @param $callback the callback function to use for comparison
- * @param $reverse true if the result is to be reversed
- * @return the sorted tree
- */
- public function _sort_filelist(&$files, $callback, $reverse)
- {
- // sort subtrees
- $counter = count($files);
- // sort subtrees
- for ($i = 0; $i < $counter; $i++) {
- if ($files[$i]['children'] !== false) {
- $children = $files[$i]['children'];
- $this->_sort_filelist($children, $callback, $reverse);
- $files[$i]['children'] = $children;
- }
- }
-
- // sort current tree
- usort($files, $callback);
- if ($reverse) {
- $files = array_reverse($files);
- }
- }
-
- /**
- * Flattens the filelist by recursively walking through all subtrees and
- * merging them with a prefix attached to the filenames.
- *
- * @param $files the tree to flatten
- * @param $prefix the prefix to attach to all processed nodes
- * @return a flattened representation of the tree
- */
- public function _flatten_filelist($files, $prefix = '')
- {
- $result = [];
- foreach ($files as $file) {
- if ($file['children'] !== false) {
- $result = array_merge($result, $this->_flatten_filelist($file['children'], $prefix . $file['name'] . '/'));
- } else {
- $file['name'] = $prefix . $file['name'];
- $result[] = $file;
- }
- }
- return $result;
- }
-
- /**
- * Filters out directories and their subtrees from the result.
- *
- * @param $result the result to filter
- * @return the result without any directories contained therein,
- * DOKU_PLUGIN_FILELIST_NOMATCH if there are no files left or
- * the given result if it was not an array (but an errorcode)
- */
- public function _filter_out_directories($result)
- {
- if (!is_array($result)) {
- return $result;
- }
-
- $filtered = [];
- $files = $result['files'];
- foreach ($files as $file) {
- if ($file['children'] === false) {
- $filtered[] = $file;
- }
- }
-
- if (count($filtered) == 0) {
- return DOKU_PLUGIN_FILELIST_NOMATCH;
- } else {
- $result['files'] = $filtered;
- return $result;
- }
- }
-
- /**
- * Does a (recursive) crawl for finding files based on a given pattern.
- * Based on a safe glob reimplementation using fnmatch and opendir.
- *
- * @param $pattern the pattern to match to
- * @param params the parameters of the filelist call
- * @return a hierarchical filelist or false if nothing could be found
- *
- * @see
- */
- public function _crawl_files($pattern, $params)
- {
- $split = explode('/', $pattern);
- $match = array_pop($split);
- $path = implode('/', $split);
- if (!is_dir($path)) {
- return false;
- }
-
- $ext = explode(',', $this->getConf('extensions'));
- $ext = array_map('trim', $ext);
- $ext = array_map('preg_quote_cb', $ext);
- $ext = implode('|', $ext);
-
- if (($dir = opendir($path)) !== false) {
- $result = [];
- while (($file = readdir($dir)) !== false) {
- if ($file == '.' || $file == '..') {
- // ignore . and ..
- continue;
- }
- if ($file == $params['titlefile']) {
- // ignore the title file
- continue;
- }
- if ($file[0] == '.') {
- // ignore hidden files
- continue;
- }
- $filepath = $path . '/' . $file;
-
- if ($this->_fnmatch($match, $file) || (is_dir($filepath) && $params['recursive'])) {
- if (!is_dir($filepath) && !preg_match('/(' . $ext . ')$/i', $file)) {
- continue;
- }
-
- if (!$params['direct']) {
- // exclude prohibited media files via ACLs
- $mid = $this->_convert_mediapath($filepath);
- $perm = auth_quickaclcheck($mid);
- if ($perm < AUTH_READ) continue;
- } elseif (!is_readable($filepath)) {
- continue;
- }
-
- $filename = $file;
- if (is_dir($filepath)) {
- $titlefile = $filepath . '/' . $params['titlefile'];
- if (!$params['direct']) {
- $mid = $this->_convert_mediapath($titlefile);
- $perm = auth_quickaclcheck($mid);
- if (is_readable($titlefile) && $perm >= AUTH_READ) {
- $filename = io_readFile($titlefile, false);
- }
- } elseif (is_readable($titlefile)) {
- $filename = io_readFile($titlefile, false);
- }
- }
-
- // prepare entry
- $creator = '';
- if (!is_dir($filepath) || $params['recursive']) {
- if (!$params['direct']) {
- $medialog = new MediaChangeLog($mid);
- $revinfo = $medialog->getRevisionInfo(@filemtime(fullpath(mediaFN($mid))));
-
- if ($revinfo['user']) {
- $creator = $revinfo['user'];
- } else {
- $creator = $revinfo['ip'];
- }
- }
- if (empty($creator)) {
- $creator = $this->getLang('creatorunknown');
- }
-
- $entry = ['name' => $filename, 'path' => $filepath, 'mtime' => filemtime($filepath), 'ctime' => filectime($filepath), 'size' => filesize($filepath), 'children' => ((is_dir($filepath) && $params['recursive']) ? $this->_crawl_files($filepath . '/' . $match, $params) : false), 'treesize' => 0, 'creator' => $creator];
-
- // calculate tree size
- if ($entry['children'] !== false) {
- foreach ($entry['children'] as $child) {
- $entry['treesize'] += $child['treesize'];
- }
- } else {
- $entry['treesize'] = 1;
- }
-
- // add entry to result
- $result[] = $entry;
- }
- }
- }
- closedir($dir);
- return $result;
- } else {
- return false;
- }
- }
-
- //~~ Comparators
-
- public function _compare_names($a, $b)
- {
- return strcmp($a['name'], $b['name']);
- }
-
- public function _compare_inames($a, $b)
- {
- return strcmp(strtolower($a['name']), strtolower($b['name']));
- }
-
- public function _compare_ctimes($a, $b)
- {
- return $a['ctime'] <=> $b['ctime'];
- }
-
- public function _compare_mtimes($a, $b)
- {
- return $a['mtime'] <=> $b['mtime'];
- }
-
- public function _compare_sizes($a, $b)
- {
- return $a['size'] <=> $b['size'];
- }
-
- //~~ Utility functions
-
- /**
- * Canonicalizes a given path. A bit like realpath, but without the resolving of symlinks.
- *
- * @author anonymous
- * @see
- */
- public function _realpath($path)
- {
- $path = explode('/', $path);
- $output = [];
- $counter = count($path);
- for ($i = 0; $i < $counter; $i++) {
- if ('.' == $path[$i]) continue;
- if ('..' == $path[$i] && '..' != $output[count($output) - 1]) {
- array_pop($output);
- continue;
- }
- $output[] = $path[$i];
- }
- return implode('/', $output);
- }
-
- /**
- * Replacement for fnmatch() for windows systems.
- *
- * @author jk at ricochetsolutions dot com
- * @see
- */
- public function _fnmatch($pattern, $string)
- {
- return preg_match("#^" . strtr(preg_quote($pattern, '#'), ['\*' => '.*', '\?' => '.', '\[' => '[', '\]' => ']']) . "$#i", $string);
- }
-
- /**
- * Converts backslashs in paths to slashs.
- *
- * @param $path the path to convert
- * @return the converted path
- */
- public function _win_path_convert($path)
- {
- return str_replace('\\', '/', trim($path));
- }
-
- /**
- * Return human readable sizes
- *
- * @param int $size size in bytes
- * @param string $max maximum unit
- * @param string $system 'si' for SI, 'bi' for binary prefixes
- * @param string $retstring return string format
- * @version 1.3.0
- * @link http://aidanlister.com/repos/v/function.size_readable.php
- * @author Aidan Lister
- */
- public function _size_readable($size, $max = null, $system = 'si', $retstring = '%01.2f %s')
- {
- // Pick units
- $systems['si']['prefix'] = ['B', 'K', 'MB', 'GB', 'TB', 'PB'];
- $systems['si']['size'] = 1000;
- $systems['bi']['prefix'] = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB'];
- $systems['bi']['size'] = 1024;
- $sys = $systems[$system] ?? $systems['si'];
-
- // Max unit to display
- $depth = count($sys['prefix']) - 1;
- if ($max && false !== $d = array_search($max, $sys['prefix'])) {
- $depth = $d;
- }
-
- // Loop
- $i = 0;
- while ($size >= $sys['size'] && $i < $depth) {
- $size /= $sys['size'];
- $i++;
- }
-
- return sprintf($retstring, $size, $sys['prefix'][$i]);
- }
-
- /**
- * Determines whether a given path is absolute or relative.
- * On windows plattforms, it does so by checking whether the second character
- * of the path is a :, on all other plattforms it checks for a / as the
- * first character.
- *
- * @param $path the path to check
- * @return true if path is absolute, false otherwise
- */
- public function _path_is_absolute($path)
- {
- if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
- if ($path[1] == ':' || ($path[0] == '/' && $path[1] == '/')) {
- return true;
- }
- return false;
- } else {
- return ($path[0] == '/');
- }
- }
-
- public function _convert_mediapath($path)
- {
- $mid = str_replace('/', ':', substr($path, strlen($this->mediadir))); // strip media base dir
- return ltrim($mid, ':'); // strip leading :
- }
-
- /**
- * The function determines the preview image path for the given file
- * depending on the file type and the 'preview' config option value:
- * 1: Display file as preview image if itself is an image otherwise
- * choose DokuWiki image corresponding to the file extension
- * 2: Display file as preview image if itself is an image otherwise
- * display no image
- * 3. Display DokuWiki image corresponding to the file extension
- *
- * @param $filename the file to check
- * @return string Image to use for preview image
- */
- protected function get_preview_image_path($filename, $params, &$isImage)
- {
- [$ext, $mime] = mimetype(basename($filename));
- $imagepath = '';
- $isImage = false;
- if (
- ($params['preview'] == 1 || $params['preview'] == 2) &&
- strncmp($mime, 'image', strlen('image')) == 0
- ) {
- // The file is an image. Return itself as the image path.
- $imagepath = $filename;
- $isImage = true;
- }
- if (
- ($params['preview'] == 1 && empty($imagepath)) ||
- $params['preview'] == 3
- ) {
- // No image. Return DokuWiki image for file extension.
- if (!empty($ext)) {
- $imagepath = DOKU_INC . 'lib/images/fileicons/32x32/' . $ext . '.png';
- } else {
- $imagepath = DOKU_INC . 'lib/images/fileicons/32x32/file.png';
- }
- }
- return $imagepath;
- }
-
- /**
- * Create URL for file $filepath.
- *
- * @param $filepath the file for which a preview image shall be rendered
- * @param $basedir the basedir to use
- * @param $webdir the webdir to use
- * @param $params the parameters of the filelist call
- * @return string the generated URL
- */
- protected function _get_link_url($filepath, $basedir, $webdir, $randlinks, $direct, $ftp = false)
- {
- $urlparams = '';
- if ($randlinks) {
- $urlparams = '?' . time();
- }
- if (!$direct) {
- $url = ml(':' . $this->_convert_mediapath($filepath)) . $urlparams;
- } else {
- $url = $webdir . substr($filepath, strlen($basedir)) . $urlparams;
- if ($ftp) {
- $url = str_replace('\\', '/', $url);
- if (strpos($url, 'http') === false) {
- $url = 'ftp:' . $url;
- } else {
- $url = str_replace('http', 'ftp', $url);
- }
- }
- }
- return $url;
- }
}