/** * Returns an utf8 encoded Namespace for a Page and input Namespace * @param $NS * @param $PAGE */ function getNamespaceFromID($NS, &$PAGE) { global $conf; // Check current page - if its an NS add the startpage $clean = true; resolve_pageid(getNS($NS), $NS, $clean); if (!page_exists($NS) && array_pop(explode(':', $NS)) != strtolower($conf['start'])) { // Compare to lowercase since clean lowers it. $NS .= ':' . $conf['start']; resolve_pageid(getNS($NS), $NS, $clean); } $PAGE = noNS($NS); $NS = getNS($NS); return utf8_encodeFN(str_replace(':', '/', $NS)); }
/** * Returns an array of pages with discussion sections, sorted by recent comments * Note: also used for content by Feed Plugin * * @param string $ns * @param null|int $num * @param string|bool $skipEmpty * @return array */ function getThreads($ns, $num = null, $skipEmpty = false) { global $conf; require_once DOKU_INC . 'inc/search.php'; $dir = $conf['datadir'] . utf8_encodeFN($ns ? '/' . str_replace(':', '/', $ns) : ''); // returns the list of pages in the given namespace and it's subspaces $items = array(); search($items, $dir, 'search_allpages', array()); // add pages with comments to result $result = array(); foreach ($items as $item) { $id = ($ns ? $ns . ':' : '') . $item['id']; // some checks $perm = auth_quickaclcheck($id); if ($perm < AUTH_READ) { continue; } // skip if no permission $file = metaFN($id, '.comments'); if (!@file_exists($file)) { continue; } // skip if no comments file $data = unserialize(io_readFile($file, false)); $status = $data['status']; $number = $data['number']; if (!$status || $status == 2 && !$number) { continue; } // skip if comments are off or closed without comments if ($skipEmpty == 'y' && $number == 0) { continue; } // skip if discussion is empty and flag is set $date = filemtime($file); $meta = p_get_metadata($id); $result[$date . '_' . $id] = array('id' => $id, 'file' => $file, 'title' => $meta['title'], 'date' => $date, 'user' => $meta['creator'], 'desc' => $meta['description']['abstract'], 'num' => $number, 'comments' => $this->td($id, $number), 'status' => $status, 'perm' => $perm, 'exists' => true, 'anchor' => 'discussion__section'); } // finally sort by time of last comment krsort($result); if (is_numeric($num)) { $result = array_slice($result, 0, $num); } return $result; }
/** * Removes empty directories * * Sends IO_NAMESPACE_DELETED events for 'pages' and 'media' namespaces. * Event data: * $data[0] ns: The colon separated namespace path minus the trailing page name. * $data[1] ns_type: 'pages' or 'media' namespace tree. * * @todo use safemode hack * @author Andreas Gohr <*****@*****.**> * @author Ben Coburn <*****@*****.**> */ function io_sweepNS($id, $basedir = 'datadir') { global $conf; $types = array('datadir' => 'pages', 'mediadir' => 'media'); $ns_type = isset($types[$basedir]) ? $types[$basedir] : false; //scan all namespaces while (($id = getNS($id)) !== false) { $dir = $conf[$basedir] . '/' . utf8_encodeFN(str_replace(':', '/', $id)); //try to delete dir else return if (@rmdir($dir)) { if ($ns_type !== false) { $data = array($id, $ns_type); trigger_event('IO_NAMESPACE_DELETED', $data); } } else { return; } } }
/** * AJAX call handler for ACL plugin * * @param Doku_Event $event event object by reference * @param mixed $param empty * @return void */ public function handle_ajax_call_acl(Doku_Event &$event, $param) { if ($event->data !== 'plugin_acl') { return; } $event->stopPropagation(); $event->preventDefault(); global $ID; global $INPUT; if (!auth_isadmin()) { echo 'for admins only'; return; } if (!checkSecurityToken()) { echo 'CRSF Attack'; return; } $ID = getID(); /** @var $acl admin_plugin_acl */ $acl = plugin_load('admin', 'acl'); $acl->handle(); $ajax = $INPUT->str('ajax'); header('Content-Type: text/html; charset=utf-8'); if ($ajax == 'info') { $acl->_html_info(); } elseif ($ajax == 'tree') { $ns = $INPUT->str('ns'); if ($ns == '*') { $ns = ''; } $ns = cleanID($ns); $lvl = count(explode(':', $ns)); $ns = utf8_encodeFN(str_replace(':', '/', $ns)); $data = $acl->_get_tree($ns, $ns); foreach (array_keys($data) as $item) { $data[$item]['level'] = $lvl + 1; } echo html_buildlist($data, 'acl', array($acl, '_html_list_acl'), array($acl, '_html_li_acl')); } }
/** * List all media files. * * Available options are 'recursive' for also including the subnamespaces * in the listing, and 'pattern' for filtering the returned files against * a regular expression matching their name. * * @author Gina Haeussge <*****@*****.**> */ function listAttachments($ns, $options = array()) { global $conf; global $lang; $ns = cleanID($ns); if (!is_array($options)) { $options = array(); } if (!isset($options['recursive'])) { $options['recursive'] = false; } if (auth_quickaclcheck($ns . ':*') >= AUTH_READ) { $dir = utf8_encodeFN(str_replace(':', '/', $ns)); $data = array(); require_once DOKU_INC . 'inc/search.php'; search($data, $conf['mediadir'], 'search_media', array('recursive' => $options['recursive']), $dir); if (!count($data)) { return array(); } $files = array(); foreach ($data as $item) { if (isset($options['pattern']) && !@preg_match($options['pattern'], $item['id'])) { continue; } $file = array(); $file['id'] = $item['id']; $file['size'] = $item['size']; $file['lastModified'] = new IXR_Date($item['mtime']); $file['isimg'] = $item['isimg']; $file['writable'] = $item['writeable']; $file['perms'] = auth_quickaclcheck(getNS($item['id']) . ':*'); array_push($files, $file); } return $files; } else { return new IXR_Error(1, 'You are not allowed to list media files.'); } }
/** * Obtain list of pages and title, based on url parameters * * @param Doku_Event $event * @return string|bool */ protected function collectExportPages(Doku_Event $event) { global $ACT; global $ID; global $INPUT; global $conf; // list of one or multiple pages $list = array(); if ($ACT == 'export_odt') { $list[0] = $ID; $title = $INPUT->str('book_title'); if (!$title) { $title = p_get_first_heading($ID); } } elseif ($ACT == 'export_odtns') { //check input for title and ns if (!($title = $INPUT->str('book_title'))) { $this->showPageWithErrorMsg($event, 'needtitle'); return false; } $docnamespace = cleanID($INPUT->str('book_ns')); if (!@is_dir(dirname(wikiFN($docnamespace . ':dummy')))) { $this->showPageWithErrorMsg($event, 'needns'); return false; } //sort order $order = $INPUT->str('book_order', 'natural', true); $sortoptions = array('pagename', 'date', 'natural'); if (!in_array($order, $sortoptions)) { $order = 'natural'; } //search depth $depth = $INPUT->int('book_nsdepth', 0); if ($depth < 0) { $depth = 0; } //page search $result = array(); $opts = array('depth' => $depth); //recursive all levels $dir = utf8_encodeFN(str_replace(':', '/', $docnamespace)); search($result, $conf['datadir'], 'search_allpages', $opts, $dir); //sorting if (count($result) > 0) { if ($order == 'date') { usort($result, array($this, '_datesort')); } elseif ($order == 'pagename') { usort($result, array($this, '_pagenamesort')); } } foreach ($result as $item) { $list[] = $item['id']; } } elseif (isset($_COOKIE['list-pagelist']) && !empty($_COOKIE['list-pagelist'])) { // Here is $ACT == 'export_odtbook' //is in Bookmanager of bookcreator plugin a title given? if (!($title = $INPUT->str('book_title'))) { $this->showPageWithErrorMsg($event, 'needtitle'); return false; } else { $list = explode("|", $_COOKIE['list-pagelist']); } } else { //show empty bookcreator message $this->showPageWithErrorMsg($event, 'empty'); return false; } $list = array_map('cleanID', $list); return array($title, $list); }
/** * get to-be directory and filename (without extension) * * all files are stored in the media directory into 'plugin_abc/<namespaces>/' * and the filename is a mixture of abc-id and abc-title (e.g. 42_the_title.abc|...) * */ function _getFileBase($src) { global $ID; global $ACT; global $conf; $mediadir = $conf['mediadir']; // where to store the abc media files $abcdir = $this->getConf('mediaNS') ? $mediadir . '/' . $this->getConf('mediaNS') : $mediadir; io_makeFileDir($abcdir); $fileDir = $abcdir . '/' . utf8_encodeFN(str_replace(':', '/', getNS($ID))); // the abcID is what comes after the 'X:' preg_match("/\\s?X\\s?:(.*?)\n/se", $src, $matchesX); $abcID = preg_replace('/\\s?X\\s?:/', '', $matchesX[0]); // the abcTitle is what comes after the (first) 'T:' preg_match("/\\s?T\\s?:(.*?)\n/se", $src, $matchesT); $abcTitle = preg_replace('/\\s?T\\s?:/', '', $matchesT[0]); $fileName = cleanID($abcID . "_" . $abcTitle); // no double slash when in root namespace $slashStr = getNS($ID) ? "/" : ""; // have different fileBase for previewing $previewPrefix = $ACT != 'preview' ? "" : "x"; $fileBase = $fileDir . $slashStr . $previewPrefix . $fileName; // unfortunately abcm2ps seems not to be able to handle // file names (realpath) of more than 120 characters $realFileBaseLen = strlen(fullpath($abcdir)) - strlen($abcdir) + strlen($fileBase); $char_len = 114; if ($realFileBaseLen >= $char_len) { $truncLen = strlen($fileBase) + ($char_len - $realFileBaseLen); $fileBase = substr($fileBase, 0, $truncLen); } return $fileBase; }
function _exportContainercontent($exporter) { global $ID, $INFO, $conf; if ($ID == $conf['start']) { $title = $conf['title']; } elseif (isset($INFO['meta']['title'])) { $title = $INFO['meta']['title']; } else { $title = $ID; } $exporter->setParameters('Container: ' . $title, getAbsUrl(), getAbsUrl() . 'doku.php?', 'utf-8', $this->agentlink); // create container object $wikicontainer = new SIOCDokuWikiContainer($ID, normalizeUri($exporter->siocURL('container', $ID))); /* container is type=wiki */ if ($ID == $conf['start']) { $wikicontainer->isWiki(); } /* sioc:name */ if ($INFO['exists']) { $wikicontainer->addTitle($INFO['meta']['title']); } /* has_parent */ if ($INFO['namespace']) { $wikicontainer->addParent($INFO['namespace']); } // search next level entries (posts, sub containers) in container require_once DOKU_INC . 'inc/search.php'; $dir = utf8_encodeFN(str_replace(':', '/', $ID)); $entries = array(); $posts = array(); $containers = array(); search($entries, $conf['datadir'], 'search_index', array('ns' => $ID), $dir); foreach ($entries as $entry) { if ($entry['type'] === 'f') { // wikisite $posts[] = $entry; } elseif ($entry['type'] === 'd') { // sub container $containers[] = $entry; } } // without sub content it can't be a container (so it does not exist as a container) if (count($posts) + count($containers) == 0) { $this->_exit("HTTP/1.0 404 Not Found"); } if (count($posts) > 0) { $wikicontainer->addArticles($posts); } if (count($containers) > 0) { $wikicontainer->addContainers($containers); } //print_r($containers);die(); // add container to exporter $exporter->addObject($wikicontainer); return $exporter; }
/** * Display a tree menu to select a page or namespace * * @author Andreas Gohr <*****@*****.**> */ function _html_explorer() { global $conf; global $ID; global $lang; $dir = $conf['datadir']; $ns = $this->ns; if (empty($ns)) { $ns = dirname(str_replace(':', '/', $ID)); if ($ns == '.') { $ns = ''; } } elseif ($ns == '*') { $ns = ''; } $ns = utf8_encodeFN(str_replace(':', '/', $ns)); $data = $this->_get_tree($ns); // wrap a list with the root level around the other namespaces array_unshift($data, array('level' => 0, 'id' => '*', 'type' => 'd', 'open' => 'true', 'label' => '[' . $lang['mediaroot'] . ']')); echo html_buildlist($data, 'acl', array($this, '_html_list_acl'), array($this, '_html_li_acl')); }
/** * returns the full path to the mediafile specified by ID * * The filename is URL encoded to protect Unicode chars * * @author Andreas Gohr <*****@*****.**> * @author Kate Arzamastseva <*****@*****.**> * * @param string $id media id * @param string|int $rev empty string or revision timestamp * @return string full path */ function mediaFN($id, $rev = '') { global $conf; $id = cleanID($id); $id = str_replace(':', '/', $id); if (empty($rev)) { $fn = $conf['mediadir'] . '/' . utf8_encodeFN($id); } else { $ext = mimetype($id); $name = substr($id, 0, -1 * strlen($ext[0]) - 1); $fn = $conf['mediaolddir'] . '/' . utf8_encodeFN($name . '.' . (int) $rev . '.' . $ext[0]); } return $fn; }
} if (!auth_isadmin()) { die('for admins only'); } if (!checkSecurityToken()) { die('CRSF Attack'); } $ID = getID(); $acl = plugin_load('admin', 'acl'); $acl->handle(); $ajax = $_REQUEST['ajax']; header('Content-Type: text/html; charset=utf-8'); if ($ajax == 'info') { $acl->_html_info(); } elseif ($ajax == 'tree') { global $conf; global $ID; $dir = $conf['datadir']; $ns = $_REQUEST['ns']; if ($ns == '*') { $ns = ''; } $ns = cleanID($ns); $lvl = count(explode(':', $ns)); $ns = utf8_encodeFN(str_replace(':', '/', $ns)); $data = $acl->_get_tree($ns, $ns); foreach (array_keys($data) as $item) { $data[$item]['level'] = $lvl + 1; } echo html_buildlist($data, 'acl', array($acl, '_html_list_acl'), array($acl, '_html_li_acl')); }
/** * Build a tree outline of available media namespaces * * @author Andreas Gohr <*****@*****.**> */ function bootstrap_media_nstree($ns) { global $conf; global $lang; // currently selected namespace $ns = cleanID($ns); if (empty($ns)) { global $ID; $ns = (string) getNS($ID); } $ns_dir = utf8_encodeFN(str_replace(':', '/', $ns)); $data = array(); search($data, $conf['mediadir'], 'search_index', array('ns' => $ns_dir, 'nofiles' => true)); // wrap a list with the root level around the other namespaces array_unshift($data, array('level' => 0, 'id' => '', 'open' => 'true', 'label' => '[' . $lang['mediaroot'] . ']')); // insert the current ns into the hierarchy if it isn't already part of it $ns_parts = explode(':', $ns); $tmp_ns = ''; $pos = 0; foreach ($ns_parts as $level => $part) { if ($tmp_ns) { $tmp_ns .= ':' . $part; } else { $tmp_ns = $part; } // find the namespace parts or insert them while ($data[$pos]['id'] != $tmp_ns) { if ($pos >= count($data) || $data[$pos]['level'] <= $level + 1 && strnatcmp(utf8_encodeFN($data[$pos]['id']), utf8_encodeFN($tmp_ns)) > 0) { array_splice($data, $pos, 0, array(array('level' => $level + 1, 'id' => $tmp_ns, 'open' => 'true'))); break; } ++$pos; } } echo bootstrap_toc_html_buildlist($data, '', 'bootstrap_media_nstree_item', 'bootstrap_media_nstree_li'); }
/** * Gather all photos matching the given criteria */ function _findimages(&$data) { global $conf; $files = array(); // http URLs are supposed to be media RSS feeds if (preg_match('/^https?:\\/\\//i', $data['ns'])) { $files = $this->_loadRSS($data['ns']); $data['_single'] = false; } elseif (preg_match('/^facebook:/i', $data['ns'])) { $files = $this->_loadFacebook($data['ns']); $data['_single'] = false; } else { $dir = utf8_encodeFN(str_replace(':', '/', $data['ns'])); // all possible images for the given namespace (or a single image) if (is_file($conf['mediadir'] . '/' . $dir)) { require_once DOKU_INC . 'inc/JpegMeta.php'; $files[] = array('id' => $data['ns'], 'isimg' => preg_match('/\\.(jpe?g|gif|png)$/', $dir), 'file' => basename($dir), 'mtime' => filemtime($conf['mediadir'] . '/' . $dir), 'meta' => new JpegMeta($conf['mediadir'] . '/' . $dir)); $data['_single'] = true; } else { $depth = $data['recursive'] ? 0 : 1; search($files, $conf['mediadir'], 'search_media', array('depth' => $depth), $dir); $data['_single'] = false; } } // done, yet? $len = count($files); if (!$len) { return $files; } if ($data['single']) { return $files; } // filter images for ($i = 0; $i < $len; $i++) { if (!$files[$i]['isimg']) { unset($files[$i]); // this is faster, because RE was done before } elseif ($data['filter']) { if (!preg_match($data['filter'], noNS($files[$i]['id']))) { unset($files[$i]); } } } if ($len < 1) { return $files; } // random? if ($data['random']) { shuffle($files); } else { // sort? if ($data['sort'] == 'date') { usort($files, array($this, '_datesort')); } elseif ($data['sort'] == 'mod') { usort($files, array($this, '_modsort')); } elseif ($data['sort'] == 'title') { usort($files, array($this, '_titlesort')); } // reverse? if ($data['reverse']) { $files = array_reverse($files); } } // limits and offsets? if ($data['offset']) { $files = array_slice($files, $data['offset']); } if ($data['limit']) { $files = array_slice($files, 0, $data['limit']); } return $files; }
/** * Get a list of namespaces below the given namespace. * Recursively fetches subnamespaces. * * @param string $topns The top namespace * @return array Multi-dimensional array of all namespaces below $tns */ protected function _getNamespaceList($topns = '') { global $conf; $topns = utf8_encodeFN(str_replace(':', '/', $topns)); $excludes = $this->getConf('addpage_exclude'); if ($excludes == "") { $excludes = array(); } else { $excludes = @explode(';', strtolower($excludes)); } $searchdata = array(); search($searchdata, $conf['datadir'], 'search_namespaces', array(), $topns); $namespaces = array(); foreach ($searchdata as $ns) { foreach ($excludes as $exclude) { if (strpos($ns['id'], $exclude) === 0) { continue 2; } } $namespaces[] = $ns['id']; } return $namespaces; }
/** * Build a tree info structure from media or page directories * * @param int $type * @param string $open The hierarchy to open FIXME not supported yet * @param string $base The namespace to start from * @return array */ public function tree($type = self::TYPE_PAGES, $open = '', $base = '') { global $conf; $opendir = utf8_encodeFN(str_replace(':', '/', $open)); $basedir = utf8_encodeFN(str_replace(':', '/', $base)); $opts = array('pagesonly' => $type == self::TYPE_PAGES, 'listdirs' => true, 'listfiles' => true, 'sneakyacl' => $conf['sneaky_index'], 'showmsg' => false, 'depth' => 1); $data = array(); if ($type == self::TYPE_PAGES) { search($data, $conf['datadir'], 'search_universal', $opts, $basedir); } elseif ($type == self::TYPE_MEDIA) { search($data, $conf['mediadir'], 'search_universal', $opts, $basedir); } return $data; }
/** * Return sub index for index view * * @author Andreas Gohr <*****@*****.**> */ function ajax_index() { global $conf; require_once DOKU_INC . 'inc/search.php'; require_once DOKU_INC . 'inc/html.php'; // wanted namespace $ns = cleanID($_POST['idx']); $dir = utf8_encodeFN(str_replace(':', '/', $ns)); $lvl = count(explode(':', $ns)); $data = array(); search($data, $conf['datadir'], 'search_index', array('ns' => $ns), $dir); foreach ($data as $item) { $item['level'] = $lvl + 1; echo html_li_index($item); echo '<div class="li">'; echo html_list_index($item); echo '</div>'; echo '</li>'; } }
/** * Build a tree outline of available media namespaces * * @author Andreas Gohr <*****@*****.**> */ function media_nstree($ns) { global $conf; global $lang; // currently selected namespace $ns = cleanID($ns); if (empty($ns)) { global $ID; $ns = dirname(str_replace(':', '/', $ID)); if ($ns == '.') { $ns = ''; } } $ns = utf8_encodeFN(str_replace(':', '/', $ns)); $data = array(); search($data, $conf['mediadir'], 'search_index', array('ns' => $ns, 'nofiles' => true)); // wrap a list with the root level around the other namespaces array_unshift($data, array('level' => 0, 'id' => '', 'open' => 'true', 'label' => '[' . $lang['mediaroot'] . ']')); echo html_buildlist($data, 'idx', 'media_nstree_item', 'media_nstree_li'); }
/** * Get a list of changed files */ function _getSyncList($type = 'pages') { if (!$this->_connect()) { return array(); } global $conf; $no = $this->profno; $list = array(); $ns = $this->profiles[$no]['ns']; // get remote file list if ($type == 'pages') { $ok = $this->client->query('dokuwiki.getPagelist', $ns, array('depth' => (int) $this->profiles[$no]['depth'], 'hash' => true)); } else { $ok = $this->client->query('wiki.getAttachments', $ns, array('depth' => (int) $this->profiles[$no]['depth'], 'hash' => true)); } if (!$ok) { msg('Failed to fetch remote file list. ' . $this->client->getErrorMessage(), -1); return false; } $remote = $this->client->getResponse(); // put into synclist foreach ($remote as $item) { $list[$item['id']]['remote'] = $item; unset($list[$item['id']]['remote']['id']); } unset($remote); // get local file list $local = array(); $dir = utf8_encodeFN(str_replace(':', '/', $ns)); require_once DOKU_INC . 'inc/search.php'; if ($type == 'pages') { search($local, $conf['datadir'], 'search_allpages', array('depth' => (int) $this->profiles[$no]['depth'], 'hash' => true), $dir); } else { search($local, $conf['mediadir'], 'search_media', array('depth' => (int) $this->profiles[$no]['depth'], 'hash' => true), $dir); } // put into synclist foreach ($local as $item) { // skip identical files if ($list[$item['id']]['remote']['hash'] == $item['hash']) { unset($list[$item['id']]); continue; } $list[$item['id']]['local'] = $item; unset($list[$item['id']]['local']['id']); } unset($local); ksort($list); return $list; }
/** * returns the full path to the mediafile specified by ID * * The filename is URL encoded to protect Unicode chars * * @author Andreas Gohr <*****@*****.**> */ function mediaFN($id) { global $conf; $id = cleanID($id); $id = str_replace(':', '/', $id); $fn = $conf['mediadir'] . '/' . utf8_encodeFN($id); return $fn; }
/** * Build the browsable index of pages * * $opts['ns'] is the current namespace * * @author Andreas Gohr <*****@*****.**> * modified by Samuele Tognini <*****@*****.**> */ function _search_index(&$data, $base, $file, $type, $lvl, $opts) { global $conf; $hns = false; $return = false; $isopen = false; $skip_index = $opts['skip_index']; $skip_file = $opts['skip_file']; $headpage = $opts['headpage']; $id = pathID($file); if ($type == 'd') { // Skip folders in plugin conf if (!empty($skip_index) && preg_match($skip_index, $id)) { return false; } //check ACL (for sneaky_index namespaces too). if ($this->getConf('sneaky_index') && auth_quickaclcheck($id . ':') < AUTH_READ) { return false; } //Open requested level if ($opts['level'] > $lvl || $opts['level'] == -1) { $isopen = true; } //Search optional namespaces if (!empty($opts['nss'])) { $nss = $opts['nss']; for ($a = 0; $a < count($nss); $a++) { if (preg_match("/^" . $id . "(\$|:.+)/i", $nss[$a][0], $match)) { //It contains an optional namespace $isopen = true; } elseif (preg_match("/^" . $nss[$a][0] . "(:.*)/i", $id, $match)) { //It's inside an optional namespace if ($nss[$a][1] == -1 || substr_count($match[1], ":") < $nss[$a][1]) { $isopen = true; } else { $isopen = false; } } } } if ($opts['nons']) { return $isopen; } elseif ($opts['max'] > 0 && !$isopen && $lvl >= $opts['max']) { $isopen = false; //Stop recursive searching $return = false; //change type $type = "l"; } elseif ($opts['js']) { $return = true; } else { $return = $isopen; } //Set title and headpage $title = $this->_getTitle($id, $headpage, $hns); if (!$hns && $opts['nopg']) { $hns = $id . ":" . $conf['start']; } } else { //Nopg.Dont show pages if ($opts['nopg']) { return false; } $return = true; //Nons.Set all pages at first level if ($opts['nons']) { $lvl = 1; } //don't add if (substr($file, -4) != '.txt') { return false; } //check hiddens and acl if (isHiddenPage($id) || auth_quickaclcheck($id) < AUTH_READ) { return false; } //Skip files in plugin conf if (!empty($skip_file) && preg_match($skip_file, $id)) { return false; } //Skip headpages to hide if (!$opts['nons'] && !empty($headpage) && $opts['hide_headpage']) { if ($id == $conf['start']) { return false; } $ahp = explode(",", $headpage); foreach ($ahp as $hp) { switch ($hp) { case ":inside:": if (noNS($id) == noNS(getNS($id))) { return false; } break; case ":same:": if (@is_dir(dirname(wikiFN($id)) . "/" . utf8_encodeFN(noNS($id)))) { return false; } break; //it' s an inside start //it' s an inside start case ":start:": if (noNS($id) == $conf['start']) { return false; } break; default: if (noNS($id) == cleanID($hp)) { return false; } } } } //Set title if (!$conf['useheading'] || !($title = p_get_first_heading($id, FALSE))) { $title = noNS($id); } $title = htmlspecialchars($title, ENT_QUOTES); } $item = array('id' => $id, 'type' => $type, 'level' => $lvl, 'open' => $isopen, 'title' => $title, 'hns' => $hns, 'file' => $file, 'return' => $return); $item['sort'] = $this->_setorder($item); $data[] = $item; return $return; }
/** * List all media files. * * Available options are 'recursive' for also including the subnamespaces * in the listing, and 'pattern' for filtering the returned files against * a regular expression matching their name. * * @author Gina Haeussge <*****@*****.**> */ function listAttachments($ns, $options = array()) { global $conf; $ns = cleanID($ns); if (!is_array($options)) { $options = array(); } $options['skipacl'] = 0; // no ACL skipping for XMLRPC if (auth_quickaclcheck($ns . ':*') >= AUTH_READ) { $dir = utf8_encodeFN(str_replace(':', '/', $ns)); $data = array(); search($data, $conf['mediadir'], 'search_media', $options, $dir); $len = count($data); if (!$len) { return array(); } for ($i = 0; $i < $len; $i++) { unset($data[$i]['meta']); $data[$i]['lastModified'] = $this->api->toDate($data[$i]['mtime']); } return $data; } else { throw new RemoteAccessDeniedException('You are not allowed to list media files.', 215); } }
/** * beautify a wiki page id for the log * * The wiki page id will be transformed to a filename like string * utf8 codes will be encoded. * * @param $id wiki page id * * @author Matthias Grimm <*****@*****.**> */ function dir_prepareID($path) { $path = cleanID($path); $path = str_replace(':', '/', $path); $path = utf8_encodeFN($path); return $path; }
/** * Renders the Index * * copy of html_index located in /inc/html.php * * TODO update to new AJAX index possible? * * @author Andreas Gohr <*****@*****.**> * @author Michael Klier <*****@*****.**> */ function p_index_xhtml($ns, $pos) { require_once DOKU_INC . 'inc/search.php'; global $conf; global $ID; $dir = $conf['datadir']; $ns = cleanID($ns); #fixme use appropriate function if (empty($ns)) { $ns = dirname(str_replace(':', '/', $ID)); if ($ns == '.') { $ns = ''; } } $ns = utf8_encodeFN(str_replace(':', '/', $ns)); // extract only the headline preg_match('/<h1>.*?<\\/h1>/', p_locale_xhtml('index'), $match); print preg_replace('#<h1(.*?id=")(.*?)(".*?)h1>#', '<h1\\1sidebar_' . $pos . '_\\2\\3h1>', $match[0]); $data = array(); search($data, $conf['datadir'], 'search_index', array('ns' => $ns)); print '<div id="' . $pos . '__index__tree">' . DOKU_LF; print html_buildlist($data, 'idx', 'html_list_index', 'html_li_index'); print '</div>' . DOKU_LF; }
/** * Print index nodes * * @author Samuele Tognini <*****@*****.**> * @author Andreas Gohr <*****@*****.**> */ function print_index($ns) { require_once DOKU_PLUGIN . 'indexmenu/syntax/indexmenu.php'; global $conf; $idxm = new syntax_plugin_indexmenu_indexmenu(); $ns = $idxm->_parse_ns($ns); $level = -1; $max = 0; $data = array(); if ($_REQUEST['max'] > 0) { $max = $_REQUEST['max']; $level = $max; } $nss = $_REQUEST['nss'] ? cleanID($_REQUEST['nss']) : ''; $idxm->sort = $_REQUEST['sort']; $idxm->msort = $_REQUEST['msort']; $idxm->rsort = $_REQUEST['rsort']; $idxm->nsort = $_REQUEST['nsort']; $fsdir = "/" . utf8_encodeFN(str_replace(':', '/', $ns)); $opts = array('level' => $level, 'nons' => $_REQUEST['nons'], 'nss' => array(array($nss, 1)), 'max' => $max, 'js' => false, 'nopg' => $_REQUEST['nopg'], 'skip_index' => $idxm->getConf('skip_index'), 'skip_file' => $idxm->getConf('skip_file'), 'headpage' => $idxm->getConf('headpage'), 'hide_headpage' => $idxm->getConf('hide_headpage')); if ($idxm->sort || $idxm->msort || $idxm->rsort) { $idxm->_search($data, $conf['datadir'], array($idxm, '_search_index'), $opts, $fsdir); } else { search($data, $conf['datadir'], array($idxm, '_search_index'), $opts, $fsdir); } if ($_REQUEST['nojs']) { require_once DOKU_INC . 'inc/html.php'; $out_tmp = html_buildlist($data, 'idx', array($idxm, "_html_list_index"), "html_li_index"); $out .= preg_replace('/<ul class="idx">(.*)<\\/ul>/s', "\$1", $out_tmp); } else { $nodes = $idxm->_jsnodes($data, '', 0); $out = "ajxnodes = ["; $out .= rtrim($nodes[0], ","); $out .= "];"; } return $out; }
/** * List matching namespaces and pages for the link wizard * * @author Andreas Gohr <*****@*****.**> */ function ajax_linkwiz() { global $conf; global $lang; $q = ltrim($_POST['q'], ':'); $id = noNS($q); $ns = getNS($q); $ns = cleanID($ns); $id = cleanID($id); $nsd = utf8_encodeFN(str_replace(':', '/', $ns)); $idd = utf8_encodeFN(str_replace(':', '/', $id)); $data = array(); if ($q && !$ns) { // use index to lookup matching pages $pages = array(); $pages = ft_pageLookup($id, true); // result contains matches in pages and namespaces // we now extract the matching namespaces to show // them seperately $dirs = array(); foreach ($pages as $pid => $title) { if (strpos(noNS($pid), $id) === false) { // match was in the namespace $dirs[getNS($pid)] = 1; // assoc array avoids dupes } else { // it is a matching page, add it to the result $data[] = array('id' => $pid, 'title' => $title, 'type' => 'f'); } unset($pages[$pid]); } foreach ($dirs as $dir => $junk) { $data[] = array('id' => $dir, 'type' => 'd'); } } else { $opts = array('depth' => 1, 'listfiles' => true, 'listdirs' => true, 'pagesonly' => true, 'firsthead' => true, 'sneakyacl' => $conf['sneaky_index']); if ($id) { $opts['filematch'] = '^.*\\/' . $id; } if ($id) { $opts['dirmatch'] = '^.*\\/' . $id; } search($data, $conf['datadir'], 'search_universal', $opts, $nsd); // add back to upper if ($ns) { array_unshift($data, array('id' => getNS($ns), 'type' => 'u')); } } // fixme sort results in a useful way ? if (!count($data)) { echo $lang['nothingfound']; exit; } // output the found data $even = 1; foreach ($data as $item) { $even *= -1; //zebra if (($item['type'] == 'd' || $item['type'] == 'u') && $item['id']) { $item['id'] .= ':'; } $link = wl($item['id']); echo '<div class="' . ($even > 0 ? 'even' : 'odd') . ' type_' . $item['type'] . '">'; if ($item['type'] == 'u') { $name = $lang['upperns']; } else { $name = htmlspecialchars($item['id']); } echo '<a href="' . $link . '" title="' . htmlspecialchars($item['id']) . '" class="wikilink1">' . $name . '</a>'; if ($item['title']) { echo '<span>' . htmlspecialchars($item['title']) . '</span>'; } echo '</div>'; } }
/** * Display page index * * @author Andreas Gohr <*****@*****.**> */ function html_index($ns) { global $conf; global $ID; $dir = $conf['datadir']; $ns = cleanID($ns); #fixme use appropriate function if (empty($ns)) { $ns = dirname(str_replace(':', '/', $ID)); if ($ns == '.') { $ns = ''; } } $ns = utf8_encodeFN(str_replace(':', '/', $ns)); echo p_locale_xhtml('index'); echo '<div id="index__tree">'; $data = array(); search($data, $conf['datadir'], 'search_index', array('ns' => $ns)); echo html_buildlist($data, 'idx', 'html_list_index', 'html_li_index'); echo '</div>'; }
/** * Gives a list of pages for a given include statement * * @author Michael Hamann <*****@*****.**> */ function _get_included_pages($mode, $page, $sect, $parent_id, $flags) { global $conf; $pages = array(); switch($mode) { case 'namespace': $page = cleanID($page); $ns = utf8_encodeFN(str_replace(':', '/', $page)); // depth is absolute depth, not relative depth, but 0 has a special meaning. $depth = $flags['depth'] ? $flags['depth'] + substr_count($page, ':') + ($page ? 1 : 0) : 0; search($pagearrays, $conf['datadir'], 'search_allpages', array('depth' => $depth), $ns); if (is_array($pagearrays)) { foreach ($pagearrays as $pagearray) { if (!isHiddenPage($pagearray['id'])) // skip hidden pages $pages[] = $pagearray['id']; } } break; case 'tagtopic': if (!$this->taghelper) $this->taghelper =& plugin_load('helper', 'tag'); if(!$this->taghelper) { msg('You have to install the tag plugin to use this functionality!', -1); return array(); } $tag = $page; $sect = ''; $pagearrays = $this->taghelper->getTopic('', null, $tag); foreach ($pagearrays as $pagearray) { $pages[] = $pagearray['id']; } break; default: $page = $this->_apply_macro($page); resolve_pageid(getNS($parent_id), $page, $exists); // resolve shortcuts and clean ID if (auth_quickaclcheck($page) >= AUTH_READ) $pages[] = $page; } if (count($pages) > 1) { if ($flags['order'] === 'id') { if ($flags['rsort']) { usort($pages, array($this, '_r_strnatcasecmp')); } else { natcasesort($pages); } } else { $ordered_pages = array(); foreach ($pages as $page) { $key = ''; switch ($flags['order']) { case 'title': $key = p_get_first_heading($page); break; case 'created': $key = p_get_metadata($page, 'date created', METADATA_DONT_RENDER); break; case 'modified': $key = p_get_metadata($page, 'date modified', METADATA_DONT_RENDER); break; case 'indexmenu': $key = p_get_metadata($page, 'indexmenu_n', METADATA_RENDER_USING_SIMPLE_CACHE); if ($key === null) $key = ''; break; case 'custom': $key = p_get_metadata($page, 'include_n', METADATA_RENDER_USING_SIMPLE_CACHE); if ($key === null) $key = ''; break; } $key .= '_'.$page; $ordered_pages[$key] = $page; } if ($flags['rsort']) { uksort($ordered_pages, array($this, '_r_strnatcasecmp')); } else { uksort($ordered_pages, 'strnatcasecmp'); } $pages = $ordered_pages; } } $result = array(); foreach ($pages as $page) { $exists = page_exists($page); $result[] = array('id' => $page, 'exists' => $exists, 'parent_id' => $parent_id); } return $result; }
/** * Remove an installed theme * * @author Samuele Tognini <*****@*****.**> */ function _delete($theme) { if ($theme == "default") { return; } if ($this->_rm_dir(INDEXMENU_IMG_ABSDIR . "/" . utf8_encodeFN(basename($theme)))) { msg($this->getLang('delete_ok') . ": {$theme}.", 1); } else { msg($this->getLang('delete_no') . ": {$theme}.", -1); } }
/** * List all files in a given Media namespace * * @see media_filelist() */ function _mod_media_filelist($ns, $auth = null, $jump = '', $fullscreenview = false, $sort = false) { global $conf; global $lang; $ns = cleanID($ns); // check auth our self if not given (needed for ajax calls) if (is_null($auth)) { $auth = auth_quickaclcheck("{$ns}:*"); } if (!$fullscreenview) { echo '<h1 id="media__ns">:' . hsc($ns) . '</h1>' . NL; } if ($auth < AUTH_READ) { // FIXME: print permission warning here instead? echo '<div class="nothing">' . $lang['nothingfound'] . '</div>' . NL; } else { if (!$fullscreenview) { media_uploadform($ns, $auth); } $dir = utf8_encodeFN(str_replace(':', '/', $ns)); $data = array(); search($data, $conf['mediadir'], 'search_media', array('showmsg' => true, 'depth' => 1), $dir, 1, $sort); if (!count($data)) { echo '<div class="nothing">' . $lang['nothingfound'] . '</div>' . NL; } else { if ($fullscreenview) { echo '<ul class="' . _media_get_list_type() . '">'; } foreach ($data as $item) { if (!$fullscreenview) { $this->_mod_media_printfile($item, $auth, $jump); } else { $this->_mod_media_printfile_thumbs($item, $auth, $jump); } } if ($fullscreenview) { echo '</ul>' . NL; } } } if (!$fullscreenview) { media_searchform($ns); } }
/** * Display a tree menu to select a page or namespace * * @author Andreas Gohr <*****@*****.**> */ function _html_explorer() { require_once DOKU_INC . 'inc/search.php'; global $conf; global $ID; global $lang; $dir = $conf['datadir']; $ns = $this->ns; if (empty($ns)) { $ns = dirname(str_replace(':', '/', $ID)); if ($ns == '.') { $ns = ''; } } elseif ($ns == '*') { $ns = ''; } $ns = utf8_encodeFN(str_replace(':', '/', $ns)); $data = $this->_get_tree($ns); // wrap a list with the root level around the other namespaces $item = array('level' => 0, 'id' => '*', 'type' => 'd', 'open' => 'true', 'label' => '[' . $lang['mediaroot'] . ']'); echo '<ul class="acltree">'; echo $this->_html_li_acl($item); echo '<div class="li">'; echo $this->_html_list_acl($item); echo '</div>'; echo html_buildlist($data, 'acl', array($this, '_html_list_acl'), array($this, '_html_li_acl')); echo '</li>'; echo '</ul>'; }