function indexmenu_search_index(&$data, $base, $file, $type, $lvl, $opts) { global $conf; $ret = true; $item = array(); if ($type == 'f' && !preg_match('#\\.txt$#', $file)) { // don't add return false; } // get page id by filename $id = pathID($file); // check hiddens if ($type == 'f' && isHiddenPage($id)) { return false; } // bugfix for the // /ns/ // /<ns>.txt // case, need to force the 'directory' type if ($type == 'f' && file_exists(dirname(wikiFN($id . ":" . noNS($id))))) { $type = 'd'; } // page target id = global id $target = $id; if ($type == 'd') { // this will check 3 kinds of headpage: // 1. /<ns>/<ns>.txt // 2. /<ns>/ // /<ns>.txt // 3. /<ns>/ // /<ns>/<start_page> $nsa = array($id . ":" . noNS($id), $id, $id . ":" . $conf['start']); $nspage = false; foreach ($nsa as $nsp) { if (@file_exists(wikiFN($nsp)) && auth_quickaclcheck($nsp) >= AUTH_READ) { $nspage = $nsp; break; } } //headpage exists if ($nspage) { $target = $nspage; } else { // open namespace index, if headpage does not exists $target = $target . ':'; } } $data[] = array('id' => $id, 'date' => @filectime(wikiFN($target)), 'type' => $type, 'target' => $target, 'title' => $conf['useheading'] && ($title = p_get_first_heading($target)) ? $title : $id, 'level' => $lvl); if (substr_count($id, ":") > 2) { $ret = 0; } return $ret; }
/** * Builds a Google Sitemap of all public pages known to the indexer * * The map is placed in the cache directory named sitemap.xml.gz - This * file needs to be writable! * * @author Michael Hamann * @author Andreas Gohr * @link https://www.google.com/webmasters/sitemaps/docs/en/about.html * @link http://www.sitemaps.org/ */ public function generate() { global $conf; if ($conf['sitemap'] < 1 || !is_numeric($conf['sitemap'])) { return false; } $sitemap = Sitemapper::getFilePath(); if (@file_exists($sitemap)) { if (!is_writable($sitemap)) { return false; } } else { if (!is_writable(dirname($sitemap))) { return false; } } if (@filesize($sitemap) && @filemtime($sitemap) > time() - $conf['sitemap'] * 86400) { // 60*60*24=86400 dbglog('Sitemapper::generate(): Sitemap up to date'); // FIXME: only in debug mode return false; } dbglog("Sitemapper::generate(): using {$sitemap}"); // FIXME: Only in debug mode $pages = idx_getIndex('page', ''); dbglog('Sitemapper::generate(): creating sitemap using ' . count($pages) . ' pages'); $items = array(); // build the sitemap items foreach ($pages as $id) { //skip hidden, non existing and restricted files if (isHiddenPage($id)) { continue; } if (auth_aclcheck($id, '', '') < AUTH_READ) { continue; } $item = SitemapItem::createFromID($id); if ($item !== NULL) { $items[] = $item; } } $eventData = array('items' => &$items, 'sitemap' => &$sitemap); $event = new Doku_Event('SITEMAP_GENERATE', $eventData); if ($event->advise_before(true)) { //save the new sitemap $result = io_saveFile($sitemap, Sitemapper::getXML($items)); } $event->advise_after(); return $result; }
/** * called when(after) writing a new page to disk. * publishing is triggered from here. * see http://www.dokuwiki.org/devel:events_list#io_wikipage_write */ function handle_wikipage_write(&$event, $param) { global $ID; if (!$this->getConf('enable publishing')) { return; } // if an old revision is safed -> run away if ($event->data[3]) { return true; } $ns = $event->data[1]; $name = $event->data[2]; #$path=$event->data[0][0]; if (empty($event->data[0][1])) { //page has been deleted } if ($ID != $ns . (!empty($ns) ? ':' : '') . $name) { msg('rpcpub: not publishing wiki-page other than current page ID="' . $ID . '" <> file="' . $ns . ':' . $name . '"'); $this->_debug('rpcpub: not publishing wiki-page other than current page ID="' . $ID . '" <> file="' . $ns . ':' . $name . '"'); # Note: this prevents publish loops, the XML-RPC does not set $ID. return true; } # check if anonymous users can READ this before publishing. #if(auth_quickaclcheck($ID) < AUTH_EDIT || auth_aclcheck($ID, '', array()) < AUTH_READ){ # return true; #} if (isHiddenPage($ID)) { return true; } $meta = p_get_metadata($ID); # skip '~~DRAFT~~' - requires the blog plugin. if ($meta['type'] == 'draft') { return true; } # TODO: check for other meta-data, namespace-blacklist, etc. # TODO: prevent publish loops. $this->_wikiRpcPublish($ID); return true; }
/** * Internal function used by $this->getComments() * * don't call directly * * @see getRecentComments() * @author Andreas Gohr <*****@*****.**> * @author Ben Coburn <*****@*****.**> * @author Esther Brunner <*****@*****.**> * * @param string $line * @param string $ns * @param array $seen * @return array|bool */ function _handleRecentComment($line, $ns, &$seen) { if (empty($line)) { return false; } //skip empty lines // split the line into parts $recent = parseChangelogLine($line); if ($recent === false) { return false; } $cid = $recent['extra']; $fullcid = $recent['id'] . '#' . $recent['extra']; // skip seen ones if (isset($seen[$fullcid])) { return false; } // skip 'show comment' log entries if ($recent['type'] === 'sc') { return false; } // remember in seen to skip additional sights $seen[$fullcid] = 1; // check if it's a hidden page or comment if (isHiddenPage($recent['id'])) { return false; } if ($recent['type'] === 'hc') { return false; } // filter namespace or id if ($ns && strpos($recent['id'] . ':', $ns . ':') !== 0) { return false; } // check ACL $recent['perm'] = auth_quickaclcheck($recent['id']); if ($recent['perm'] < AUTH_READ) { return false; } // check existance $recent['file'] = wikiFN($recent['id']); $recent['exists'] = @file_exists($recent['file']); if (!$recent['exists']) { return false; } if ($recent['type'] === 'dc') { return false; } // get discussion meta file name $data = unserialize(io_readFile(metaFN($recent['id'], '.comments'), false)); // check if discussion is turned off if ($data['status'] === 0) { return false; } $parent_id = $cid; // Check for the comment and all parents if they exist and are visible. do { $tcid = $parent_id; // check if the comment still exists if (!isset($data['comments'][$tcid])) { return false; } // check if the comment is visible if ($data['comments'][$tcid]['show'] != 1) { return false; } $parent_id = $data['comments'][$tcid]['parent']; } while ($parent_id && $parent_id != $tcid); // okay, then add some additional info if (is_array($data['comments'][$cid]['user'])) { $recent['name'] = $data['comments'][$cid]['user']['name']; } else { $recent['name'] = $data['comments'][$cid]['name']; } $recent['desc'] = strip_tags($data['comments'][$cid]['xhtml']); $recent['anchor'] = 'comment_' . $cid; return $recent; }
/** * Build the browsable index of pages * * $opts['ns'] is the current namespace * * @author Andreas Gohr <*****@*****.**> */ function search_index(&$data, $base, $file, $type, $lvl, $opts) { global $conf; $return = true; $item = array(); if ($type == 'd' && !preg_match('#^' . $file . '(/|$)#', '/' . $opts['ns'])) { //add but don't recurse $return = false; } elseif ($type == 'f' && ($opts['nofiles'] || substr($file, -4) != '.txt')) { //don't add return false; } $id = pathID($file); if ($type == 'd' && $conf['sneaky_index'] && auth_quickaclcheck($id . ':') < AUTH_READ) { return false; } //check hidden if (isHiddenPage($id)) { return false; } //check ACL if ($type == 'f' && auth_quickaclcheck($id) < AUTH_READ) { return false; } $data[] = array('id' => $id, 'type' => $type, 'level' => $lvl, 'open' => $return); return $return; }
/** * Returns a list of matching documents for the given query * * @author Andreas Gohr <*****@*****.**> * @author Kazutaka Miyasaka <*****@*****.**> */ function _ft_pageSearch(&$data) { $Indexer = idx_get_indexer(); // parse the given query $q = ft_queryParser($Indexer, $data['query']); $data['highlight'] = $q['highlight']; if (empty($q['parsed_ary'])) { return array(); } // lookup all words found in the query $lookup = $Indexer->lookup($q['words']); // get all pages in this dokuwiki site (!: includes nonexistent pages) $pages_all = array(); foreach ($Indexer->getPages() as $id) { $pages_all[$id] = 0; // base: 0 hit } // process the query $stack = array(); foreach ($q['parsed_ary'] as $token) { switch (substr($token, 0, 3)) { case 'W+:': case 'W-:': case 'W_:': // word $word = substr($token, 3); $stack[] = (array) $lookup[$word]; break; case 'P+:': case 'P-:': // phrase $phrase = substr($token, 3); // since phrases are always parsed as ((W1)(W2)...(P)), // the end($stack) always points the pages that contain // all words in this phrase $pages = end($stack); $pages_matched = array(); foreach (array_keys($pages) as $id) { $text = utf8_strtolower(rawWiki($id)); if (strpos($text, $phrase) !== false) { $pages_matched[$id] = 0; // phrase: always 0 hit } } $stack[] = $pages_matched; break; case 'N+:': case 'N-:': // namespace $ns = substr($token, 3); $pages_matched = array(); foreach (array_keys($pages_all) as $id) { if (strpos($id, $ns) === 0) { $pages_matched[$id] = 0; // namespace: always 0 hit } } $stack[] = $pages_matched; break; case 'AND': // and operation list($pages1, $pages2) = array_splice($stack, -2); $stack[] = ft_resultCombine(array($pages1, $pages2)); break; case 'OR': // or operation list($pages1, $pages2) = array_splice($stack, -2); $stack[] = ft_resultUnite(array($pages1, $pages2)); break; case 'NOT': // not operation (unary) $pages = array_pop($stack); $stack[] = ft_resultComplement(array($pages_all, $pages)); break; } } $docs = array_pop($stack); if (empty($docs)) { return array(); } // check: settings, acls, existence foreach (array_keys($docs) as $id) { if (isHiddenPage($id) || auth_quickaclcheck($id) < AUTH_READ || !page_exists($id, '', false)) { unset($docs[$id]); } } // sort docs by count arsort($docs); return $docs; }
/** * Returns update logs within the period */ function _getUpdates($start, $end, $logfiles, $type) { $updates = array(); // get update log entries within the target period foreach ($logfiles as $class => $logfile) { $updates = array_merge($updates, $this->_getLogEntries($start, $end, $logfile, $class)); } // apply filter ('sub_selfmod' is applied later) switch ($type) { case 'admin': $updates_filtered = $updates; break; case 'subscribers': foreach ($updates as $entry) { if (isset($this->_skip['sub_hidden']) && $entry['class'] === 'page' && isHiddenPage($entry['id']) || isset($this->_skip['sub_media']) && $entry['class'] === 'media' || isset($this->_skip['sub_minoredit']) && $entry['type'] === 'e') { continue; // skip hidden page, media file, minor edit } $updates_filtered[] = $entry; } break; case 'register': foreach ($updates as $entry) { if (isset($this->_skip['reg_by_admin']) && $entry['extra'] === 'by-admin' || isset($this->_skip['reg_not_reg']) && $entry['type'] !== 'C') { continue; // skip usermods by admin, other than registration } $updates_filtered[] = $entry; } break; } $updates = is_null($updates_filtered) ? array() : $updates_filtered; // any updates? if (empty($updates)) { $this->_debug("No update has been made during this period ({$type})"); $this->_debug(' ' . dformat($start) . ' - ' . dformat($end)); } else { sort($updates); } return $updates; }
/** * Create output */ function render($format, &$R, $data) { global $conf; global $lang; global $ID; if ($format != 'xhtml') { return false; } $opts = array('depth' => $data['depth'], 'listfiles' => true, 'listdirs' => false, 'pagesonly' => true, 'firsthead' => true, 'meta' => true); if ($data['dirs']) { $opts['listdirs'] = true; if ($data['files']) { $opts['listfiles'] = true; } else { $opts['listfiles'] = false; } } // read the directory $result = array(); search($result, $conf['datadir'], 'search_universal', $opts, $data['dir']); if ($data['fsort']) { usort($result, array($this, '_sort_file')); } elseif ($data['dsort']) { usort($result, array($this, '_sort_date')); } else { usort($result, array($this, '_sort_page')); } $start = cleanID($data['ns'] . ':' . $conf['start']); $R->listu_open(); foreach ($result as $item) { $skip_it = false; if ($data['nostart'] and $item['file'] == $conf['start'] . '.txt') { $skip_it = true; } else { if (!$data['me'] and $item['id'] == $ID) { $skip_it = true; } else { if (isHiddenPage($item['id'])) { $skip_it = true; } else { if ($item['type'] == 'd') { $P = resolve_id($item['id'], $conf['start'], false); if (!$data['any'] and !page_exists($P)) { $skip_it = true; } } else { $P = ':' . $item['id']; } } } } if (!$skip_it) { $R->listitem_open(1); $R->listcontent_open(); $R->internallink($P); if ($data['date']) { $R->cdata(' ' . dformat($item['mtime'])); } $R->listcontent_close(); $R->listitem_close(); } } $R->listu_close(); return true; }
/** * 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; }
/** * Returns the backlinks for a given page * * Uses the metadata index. */ function ft_backlinks($id) { $result = array(); $result = idx_get_indexer()->lookupKey('relation_references', $id); if (!count($result)) { return $result; } // check ACL permissions and modify for !Researchr $remove_ns = '/^(kbib|abib|jbib|bib|start)/'; $pattern = '/^(clip:|skimg:|kindle:|notes:)(.*)$/'; foreach (array_keys($result) as $idx) { if (isHiddenPage($result[$idx]) || auth_quickaclcheck($result[$idx]) < AUTH_READ || !page_exists($result[$idx], '', false) || preg_match($remove_ns, $result[$idx])) { unset($result[$idx]); } // modify links !Researchr if (preg_match($pattern, $result[$idx], $matches)) { $result[] = "ref:" . $matches[2]; unset($result[$idx]); } } sort($result); return $result; }
/** * A heavily customised version of _ft_pageLookup in inc/fulltext.php * no sorting! */ function page_lookup($query, $fullregex, $incl_ns, $excl_ns) { global $conf; $query = trim($query); $pages = idx_get_indexer()->getPages(); if (!$fullregex) { // first deal with excluded namespaces, then included, order matters! $pages = $this->_filter_ns($pages, $excl_ns, true); $pages = $this->_filter_ns($pages, $incl_ns, false); } $cnt = count($pages); for ($i = 0; $i < $cnt; $i++) { $page = $pages[$i]; if (!page_exists($page) || isHiddenPage($page)) { unset($pages[$i]); continue; } if (!$fullregex) { $page = noNS($page); } /* * This is the actual "search" expression. * Note: preg_grep cannot be used because we need to * allow for beginning of string "^" regex on normal page search * and the page-exists check above * The @ prevents problems with invalid queries! */ $matched = @preg_match('/' . $query . '/iS', $page); if ($matched === false) { return false; } elseif ($matched == 0) { unset($pages[$i]); } } if (count($pages) > 0) { return $pages; } else { // we always return an array type return array(); } }
/** * Get blog entries from a given namespace */ function getBlog($ns, $num = NULL) { global $conf; // add pages in given namespace $result = array(); global $conf; require_once DOKU_INC . 'inc/search.php'; $pages = array(); $unique_keys_memoize = array(); $dir = str_replace(':', '/', $ns); search($pages, $conf['datadir'], 'search_pagename', array('query' => '.txt'), $dir); foreach ($pages as $page) { $id = $page['id']; $file = wikiFN($id); // do some checks first if (isHiddenPage($id)) { continue; } // skip excluded pages $excluded_pages = $this->getConf('excluded_pages'); if (strlen($excluded_pages) > 0 && preg_match($excluded_pages, $id)) { continue; } if ($ns && strpos($id, $ns . ':') !== 0) { continue; } // filter namespaces if (!@file_exists($file)) { continue; } // skip deleted $perm = auth_quickaclcheck($id); if ($perm < AUTH_READ) { continue; } // check ACL // skip drafts unless for users with create priviledge $meta = p_get_metadata($id, '', false); $draft = $meta['type'] == 'draft'; if ($draft && $perm < AUTH_CREATE) { continue; } $date = $meta['date']['modified']; if (!$date) { $date = filemtime(wikiFN($id)); } if ($this->sort != 'mdate') { $cdate = $meta['date']['created']; if (!$cdate) { $cdate = filectime(wikiFN($id)); } // prefer the date further in the past: $date = min($date, $cdate); } $title = $meta['title']; // determine the sort key if ($this->sort == 'id') { $key = $id; } elseif ($this->sort == 'pagename') { $key = noNS($id); } elseif ($this->sort == 'title') { $key = $title; } else { $key = $date; } // get a unique sortable key $key = $this->_uniqueKey($key, $unique_keys_memoize); $result[$key] = array('id' => $id, 'title' => $title, 'date' => $date, 'user' => $meta['creator'], 'desc' => $meta['description']['abstract'], 'exists' => true, 'perm' => $perm, 'draft' => $draft); } // finally sort by sort key if ($this->getConf('sortorder') == 'ascending') { ksort($result); } else { krsort($result); } if (is_numeric($num)) { $result = array_slice($result, 0, $num); } return $result; }
/** * Based on _handleRecent() from inc/changelog.php */ function handleChangelogLine($line, $ns, $type, $user, &$seen) { // split the line into parts $change = parseChangelogLine($line); if ($change === false) { return false; } // skip seen ones if (isset($seen[$change['id']])) { return false; } // filter type if (!empty($type) && !in_array($change['type'], $type)) { return false; } // filter user if (!empty($user) && (empty($change['user']) || !in_array($change['user'], $user))) { return false; } // remember in seen to skip additional sights $seen[$change['id']] = 1; // check if it's a hidden page if (isHiddenPage($change['id'])) { return false; } // filter included namespaces if (isset($ns['include'])) { if (!$this->isInNamespace($ns['include'], $change['id'])) { return false; } } // filter excluded namespaces if (isset($ns['exclude'])) { if ($this->isInNamespace($ns['exclude'], $change['id'])) { return false; } } // check ACL $change['perms'] = auth_quickaclcheck($change['id']); if ($change['perms'] < AUTH_READ) { return false; } return $change; }
/** * A heavily customised version of _ft_pageLookup in inc/fulltext.php * no sorting! */ private function _page_lookup($query, $pageonly, $incl_ns, $excl_ns, $nostart = true, $maxns = 0) { global $conf; $queries = trim($query); $pages = file($conf['indexdir'] . '/page.idx'); // first deal with excluded namespaces, then included $pages = $this->_filter_ns($pages, $excl_ns, true); // now include ONLY the selected namespaces if provided $pages = $this->_filter_ns($pages, $incl_ns, false); $cnt = count($pages); for ($i = 0; $i < $cnt; $i++) { $page = $pages[$i]; if (!page_exists($page) || isHiddenPage($page)) { unset($pages[$i]); continue; } if ($pageonly) { $page = noNS($page); } /* * This is the actual "search" expression! * Note: preg_grep cannot be used because of the pageonly option above * (needs to allow for "^" syntax) * The @ prevents problems with invalid queries! */ if (@preg_match('/' . $query . '/i', $page) == 0) { unset($pages[$i]); } } if (!count($pages)) { return array(); } $pages = array_map('trim', $pages); // check ACL permissions and remove any 'start' pages if req'd $start = $conf['start']; $pos = strlen($start); foreach ($pages as $idx => $name) { if ($nostart && substr($name, -$pos) == $start) { unset($pages[$idx]); // TODO: this function is one of slowest in the plugin; solutions? } elseif (auth_quickaclcheck($pages[$idx]) < AUTH_READ) { unset($pages[$idx]); } elseif ($maxns > 0 && substr_count($name, ':') + 1 > $maxns) { unset($pages[$idx]); } } return $pages; }
/** * Return the monthly archive list */ function _monthArchive($ns, $month, $year) { global $conf; // calculate start and end times $nextmonth = $month + 1; $year2 = $year; if ($nextmonth > 12) { $nextmonth = 1; $year2 = $year + 1; } $monthstart = mktime(0, 0, 0, $month, 1, $year); $monthend = mktime(0, 0, 0, $nextmonth, 1, $year2); // load page and creation date index $page_idx = file($conf['cachedir'] . '/page.idx'); $cdate_idx = file($conf['cachedir'] . '/cdate.idx'); // add pages in given namespace $result = array(); $c = count($page_idx); for ($i = 0; $i < $c; $i++) { $id = substr($page_idx[$i], 0, -1); // do some checks first if (isHiddenPage($id)) { continue; } // skip excluded pages if ($ns && strpos($id, $ns . ':') !== 0) { continue; } // filter namespaces if (!@file_exists(wikiFN($id))) { continue; } // skip deleted $perm = auth_quickaclcheck($id); if ($perm < AUTH_READ) { continue; } // check ACL // in right date range? $cdate = substr($cdate_idx[$i], 0, -1); if (!$cdate) { $cdate = $this->_getCdate($id, $i, $cdate_idx); } if ($monthstart > $cdate || $cdate >= $monthend) { continue; } // okay, add the page $meta = p_get_metadata($id); $result[$cdate] = array('id' => $id, 'title' => $meta['title'], 'user' => $meta['creator'], 'date' => $cdate, 'exists' => true, 'perm' => $perm); } // finally sort by creation time krsort($result); return $result; }
/** * Internal function used by $this->getLinkbacks() * * don't call directly * * @see getRecentComments() * @author Andreas Gohr <*****@*****.**> * @author Ben Coburn <*****@*****.**> * @author Esther Brunner <*****@*****.**> * @author Gina Haeussge <*****@*****.**> */ function _handleRecentLinkback($line, $ns) { static $seen = array(); //caches seen pages and skip them if (empty($line)) { return false; } //skip empty lines // split the line into parts $recent = parseChangelogLine($line); if ($recent === false) { return false; } $lid = $recent['extra']; $fulllid = $recent['id'] . '#' . $recent['extra']; // skip seen ones if (isset($seen[$fulllid])) { return false; } // skip 'show comment' log entries if ($recent['type'] === 'sc') { return false; } // remember in seen to skip additional sights $seen[$fulllid] = 1; // check if it's a hidden page or comment if (isHiddenPage($recent['id'])) { return false; } if ($recent['type'] === 'hl') { return false; } // filter namespace or id if ($ns && strpos($recent['id'] . ':', $ns . ':') !== 0) { return false; } // check ACL $recent['perm'] = auth_quickaclcheck($recent['id']); if ($recent['perm'] < AUTH_READ) { return false; } // check existance $recent['file'] = wikiFN($recent['id']); $recent['exists'] = @file_exists($recent['file']); if (!$recent['exists']) { return false; } if ($recent['type'] === 'dc') { return false; } // get linkback meta file name $data = unserialize(io_readFile(metaFN($recent['id'], '.linkbacks'), false)); // check if discussion is turned off if (!$data['display']) { return false; } // okay, then add some additional info $recent['name'] = $data['receivedpings'][$lid]['url']; $recent['desc'] = $data['receivedpings'][$lid]['excerpt']; return $recent; }
/** * Check visibility of the page * * @param string $id the page id * @param array $namespaces the namespace authorized * @return bool if the page is hidden */ function _notVisible($id, $include_namespaces = array(), $exclude_namespaces = array()) { if (isHiddenPage($id)) { return true; } // discard hidden pages // discard if user can't read if (auth_quickaclcheck($id) < AUTH_READ) { return true; } if ($include_namespaces) { $idNS = getNS($id); $found = false; foreach ((array) $include_namespaces as $ns) { // filter by namespace, root namespace is identified with a dot if ($ns == '.' && $idNS == false) { $found = true; } elseif (strpos(':' . $idNS . ':', ':' . $ns . ':') === 0) { $found = true; } } foreach ((array) $exclude_namespaces as $ns) { // filter by namespace, root namespace is identified with a dot if ($ns == '.' && $idNS == false) { $found = false; } elseif (strpos(':' . $idNS . ':', ':' . $ns . ':') === 0) { $found = false; } } if (false === $found) { return true; } } return !page_exists($id, '', false); }
/** * Returns the pages that use a given media file * * Uses the relation media metadata property and the metadata index. * * Note that before 2013-07-31 the second parameter was the maximum number of results and * permissions were ignored. That's why the parameter is now checked to be explicitely set * to true (with type bool) in order to be compatible with older uses of the function. * * @param string $id The media id to look for * @param bool $ignore_perms Ignore hidden pages and acls (optional, default: false) * @return array A list of pages that use the given media file */ function ft_mediause($id, $ignore_perms = false) { $result = idx_get_indexer()->lookupKey('relation_media', $id); if (!count($result)) { return $result; } // check ACL permissions foreach (array_keys($result) as $idx) { if ($ignore_perms !== true && (isHiddenPage($result[$idx]) || auth_quickaclcheck($result[$idx]) < AUTH_READ) || !page_exists($result[$idx], '', false)) { unset($result[$idx]); } } sort($result); return $result; }
/** * Based on _handleRecent() from inc/changelog.php * * @param string $line * @param array $ns * @param array $excludedpages * @param array $type * @param array $user * @param int $maxage * @param array $seen * @return array|bool */ protected function handleChangelogLine($line, $ns, $excludedpages, $type, $user, $maxage, &$seen) { // split the line into parts $change = parseChangelogLine($line); if ($change === false) { return false; } // skip seen ones if (isset($seen[$change['id']])) { return false; } // filter type if (!empty($type) && !in_array($change['type'], $type)) { return false; } // filter user if (!empty($user) && (empty($change['user']) || !in_array($change['user'], $user))) { return false; } // remember in seen to skip additional sights $seen[$change['id']] = 1; // show only not existing pages for delete if ($change['type'] != 'D' && !page_exists($change['id'])) { return false; } // filter maxage if ($maxage && $change['date'] < time() - $maxage) { return false; } // check if it's a hidden page if (isHiddenPage($change['id'])) { return false; } // filter included namespaces if (isset($ns['include'])) { if (!$this->isInNamespace($ns['include'], $change['id'])) { return false; } } // filter excluded namespaces if (isset($ns['exclude'])) { if ($this->isInNamespace($ns['exclude'], $change['id'])) { return false; } } // exclude pages if (!empty($excludedpages)) { foreach ($excludedpages as $page) { if ($change['id'] == $page) { return false; } } } // check ACL $change['perms'] = auth_quickaclcheck($change['id']); if ($change['perms'] < AUTH_READ) { return false; } return $change; }
/** * Internal function used by getRecents * * don't call directly * * @see getRecents() * @author Andreas Gohr <*****@*****.**> * @author Ben Coburn <*****@*****.**> */ function _handleRecent($line, $ns, $flags, &$seen) { if (empty($line)) { return false; } //skip empty lines // split the line into parts $recent = parseChangelogLine($line); if ($recent === false) { return false; } // skip seen ones if (isset($seen[$recent['id']])) { return false; } // skip minors if ($recent['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT && $flags & RECENTS_SKIP_MINORS) { return false; } // remember in seen to skip additional sights $seen[$recent['id']] = 1; // check if it's a hidden page if (isHiddenPage($recent['id'])) { return false; } // filter namespace if ($ns && strpos($recent['id'], $ns . ':') !== 0) { return false; } // exclude subnamespaces if ($flags & RECENTS_SKIP_SUBSPACES && getNS($recent['id']) != $ns) { return false; } // check ACL if ($flags & RECENTS_MEDIA_CHANGES) { $recent['perms'] = auth_quickaclcheck(getNS($recent['id']) . ':*'); } else { $recent['perms'] = auth_quickaclcheck($recent['id']); } if ($recent['perms'] < AUTH_READ) { return false; } // check existance if ($flags & RECENTS_SKIP_DELETED) { $fn = $flags & RECENTS_MEDIA_CHANGES ? mediaFN($recent['id']) : wikiFN($recent['id']); if (!@file_exists($fn)) { return false; } } return $recent; }
/** * Reverse of isHiddenPage * * @author Andreas Gohr <*****@*****.**> * * @param string $id page id * @return bool */ function isVisiblePage($id) { return !isHiddenPage($id); }
/** * Internal function used by getRecents * * don't call directly * * @see getRecents() * @author Andreas Gohr <*****@*****.**> * @author Ben Coburn <*****@*****.**> */ function _handleRecent($line, $ns, $flags) { static $seen = array(); //caches seen pages and skip them if (empty($line)) { return false; } //skip empty lines // split the line into parts $recent = parseChangelogLine($line); if ($recent === false) { return false; } // skip seen ones if (isset($seen[$recent['id']])) { return false; } // skip minors if ($recent['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT && $flags & RECENTS_SKIP_MINORS) { return false; } // remember in seen to skip additional sights $seen[$recent['id']] = 1; // check if it's a hidden page if (isHiddenPage($recent['id'])) { return false; } // filter namespace if ($ns && strpos($recent['id'], $ns . ':') !== 0) { return false; } // exclude subnamespaces if ($flags & RECENTS_SKIP_SUBSPACES && getNS($recent['id']) != $ns) { return false; } // check ACL if (auth_quickaclcheck($recent['id']) < AUTH_READ) { return false; } // check existance if (!@file_exists(wikiFN($recent['id'])) && $flags & RECENTS_SKIP_DELETED) { return false; } return $recent; }
function exportSioc() { global $ID, $INFO, $conf, $REV, $auth; // Test for hidden pages if (isHiddenPage($ID)) { $this->_exit("HTTP/1.0 404 Not Found"); } // Get type of SIOC content $sioc_type = $this->_getContenttype(); // Test for valid types if (!($sioc_type == 'post' && $INFO['exists'] || $sioc_type == 'user' || $sioc_type == 'container')) { $this->_exit("HTTP/1.0 404 Not Found"); } // Test for permission if (!$INFO['perm']) { // not enough rights to see the wiki page $this->_exit("HTTP/1.0 401 Unauthorized"); } // Forward to URI with explicit type attribut if (!isset($_GET['type'])) { header('Location:' . $_SERVER['REQUEST_URI'] . '&type=' . $sioc_type, true, 302); } // Include SIOC libs require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'sioc_inc.php'; require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'sioc_dokuwiki.php'; // Create exporter $rdf = new SIOCExporter(); $rdf->_profile_url = normalizeUri(getAbsUrl(exportlink($ID, 'siocxml', array('type' => $sioc_type), false, '&'))); $rdf->setURLParameters('type', 'id', 'page', false); // Create SIOC-RDF content switch ($sioc_type) { case 'container': $rdf = $this->_exportContainercontent($rdf); break; case 'user': $rdf = $this->_exportUsercontent($rdf); break; case 'post': default: $rdf = $this->_exportPostcontent($rdf); break; } // export if ($this->getConf('noindx')) { header("X-Robots-Tag: noindex", true); } $rdf->export(); //print_r(headers_list()); die(); die; }
/** * Builds a Google Sitemap of all public pages known to the indexer * * The map is placed in the root directory named sitemap.xml.gz - This * file needs to be writable! * * @author Andreas Gohr * @link https://www.google.com/webmasters/sitemaps/docs/en/about.html */ function runSitemapper() { global $conf; print "runSitemapper(): started" . NL; if (!$conf['sitemap']) { return false; } if ($conf['compression'] == 'bz2' || $conf['compression'] == 'gz') { $sitemap = 'sitemap.xml.gz'; } else { $sitemap = 'sitemap.xml'; } print "runSitemapper(): using {$sitemap}" . NL; if (@file_exists(DOKU_INC . $sitemap)) { if (!is_writable(DOKU_INC . $sitemap)) { return false; } } else { if (!is_writable(DOKU_INC)) { return false; } } if (@filesize(DOKU_INC . $sitemap) && @filemtime(DOKU_INC . $sitemap) > time() - $conf['sitemap'] * 60 * 60 * 24) { print 'runSitemapper(): Sitemap up to date' . NL; return false; } $pages = file($conf['indexdir'] . '/page.idx'); print 'runSitemapper(): creating sitemap using ' . count($pages) . ' pages' . NL; // build the sitemap ob_start(); print '<?xml version="1.0" encoding="UTF-8"?>' . NL; print '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . NL; foreach ($pages as $id) { $id = trim($id); $file = wikiFN($id); //skip hidden, non existing and restricted files if (isHiddenPage($id)) { continue; } $date = @filemtime($file); if (!$date) { continue; } if (auth_aclcheck($id, '', '') < AUTH_READ) { continue; } print ' <url>' . NL; print ' <loc>' . wl($id, '', true) . '</loc>' . NL; print ' <lastmod>' . date_iso8601($date) . '</lastmod>' . NL; print ' </url>' . NL; } print '</urlset>' . NL; $data = ob_get_contents(); ob_end_clean(); //save the new sitemap io_saveFile(DOKU_INC . $sitemap, $data); //ping search engines... $http = new DokuHTTPClient(); $http->timeout = 8; //ping google print 'runSitemapper(): pinging google' . NL; $url = 'http://www.google.com/webmasters/sitemaps/ping?sitemap='; $url .= urlencode(DOKU_URL . $sitemap); $resp = $http->get($url); if ($http->error) { print 'runSitemapper(): ' . $http->error . NL; } print 'runSitemapper(): ' . preg_replace('/[\\n\\r]/', ' ', strip_tags($resp)) . NL; //ping yahoo print 'runSitemapper(): pinging yahoo' . NL; $url = 'http://search.yahooapis.com/SiteExplorerService/V1/updateNotification?appid=dokuwiki&url='; $url .= urlencode(DOKU_URL . $sitemap); $resp = $http->get($url); if ($http->error) { print 'runSitemapper(): ' . $http->error . NL; } print 'runSitemapper(): ' . preg_replace('/[\\n\\r]/', ' ', strip_tags($resp)) . NL; //ping microsoft print 'runSitemapper(): pinging microsoft' . NL; $url = 'http://www.bing.com/webmaster/ping.aspx?siteMap='; $url .= urlencode(DOKU_URL . $sitemap); $resp = $http->get($url); if ($http->error) { print 'runSitemapper(): ' . $http->error . NL; } print 'runSitemapper(): ' . preg_replace('/[\\n\\r]/', ' ', strip_tags($resp)) . NL; print 'runSitemapper(): finished' . NL; return true; }
/** * Check visibility of the page * * @param string $id the page id * @param string $ns the namespace authorized * @return bool if the page is hidden */ function _notVisible($id, $ns = "") { if (isHiddenPage($id)) { return true; } // discard hidden pages // discard if user can't read if (auth_quickaclcheck($id) < AUTH_READ) { return true; } // filter by namespace, root namespace is identified with a dot if ($ns == '.') { // root namespace is specified, discard all pages who lay outside the root namespace if (getNS($id) != false) { return true; } } else { // ("!==0" namespace found at position 0) if ($ns && strpos(':' . getNS($id) . ':', ':' . $ns . ':') !== 0) { return true; } } return !page_exists($id, '', false); }
/** * 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; }
/** * This is a very universal callback for the search() function, replacing * many of the former individual functions at the cost of a more complex * setup. * * How the function behaves, depends on the options passed in the $opts * array, where the following settings can be used. * * depth int recursion depth. 0 for unlimited * keeptxt bool keep .txt extension for IDs * listfiles bool include files in listing * listdirs bool include namespaces in listing * pagesonly bool restrict files to pages * skipacl bool do not check for READ permission * sneakyacl bool don't recurse into nonreadable dirs * hash bool create MD5 hash for files * meta bool return file metadata * filematch string match files against this regexp * idmatch string match full ID against this regexp * dirmatch string match directory against this regexp when adding * nsmatch string match namespace against this regexp when adding * recmatch string match directory against this regexp when recursing * showmsg bool warn about non-ID files * showhidden bool show hidden files too * firsthead bool return first heading for pages * * @author Andreas Gohr <*****@*****.**> */ function search_universal(&$data, $base, $file, $type, $lvl, $opts) { $item = array(); $return = true; // get ID and check if it is a valid one $item['id'] = pathID($file); if ($item['id'] != cleanID($item['id'])) { if ($opts['showmsg']) { msg(hsc($item['id']) . ' is not a valid file name for DokuWiki - skipped', -1); } return false; // skip non-valid files } $item['ns'] = getNS($item['id']); if ($type == 'd') { // decide if to recursion into this directory is wanted if (!$opts['depth']) { $return = true; // recurse forever } else { $depth = substr_count($file, '/'); if ($depth >= $opts['depth']) { $return = false; // depth reached } else { $return = true; } } if ($return && !preg_match('/' . $opts['recmatch'] . '/', $file)) { $return = false; // doesn't match } } // check ACL if (!$opts['skipacl']) { if ($type == 'd') { $item['perm'] = auth_quickaclcheck($item['id'] . ':*'); } else { $item['perm'] = auth_quickaclcheck($item['id']); //FIXME check namespace for media files } } else { $item['perm'] = AUTH_DELETE; } // are we done here maybe? if ($type == 'd') { if (!$opts['listdirs']) { return $return; } if (!$opts['skipacl'] && $opts['sneakyacl'] && $item['perm'] < AUTH_READ) { return false; } //neither list nor recurse if ($opts['dirmatch'] && !preg_match('/' . $opts['dirmatch'] . '/', $file)) { return $return; } if ($opts['nsmatch'] && !preg_match('/' . $opts['nsmatch'] . '/', $item['ns'])) { return $return; } } else { if (!$opts['listfiles']) { return $return; } if (!$opts['skipacl'] && $item['perm'] < AUTH_READ) { return $return; } if ($opts['pagesonly'] && substr($file, -4) != '.txt') { return $return; } if (!$conf['showhidden'] && isHiddenPage($id)) { return $return; } if ($opts['filematch'] && !preg_match('/' . $opts['filematch'] . '/', $file)) { return $return; } if ($opts['idmatch'] && !preg_match('/' . $opts['idmatch'] . '/', $item['id'])) { return $return; } } // still here? prepare the item $item['type'] = $type; $item['level'] = $lvl; $item['open'] = $return; if ($opts['meta']) { $item['file'] = basename($file); $item['size'] = filesize($base . '/' . $file); $item['mtime'] = filemtime($base . '/' . $file); $item['rev'] = $item['mtime']; $item['writable'] = is_writable($base . '/' . $file); $item['executable'] = is_executable($base . '/' . $file); } if ($type == 'f') { if ($opts['hash']) { $item['hash'] = md5(io_readFile($base . '/' . $file, false)); } if ($opts['firsthead']) { $item['title'] = p_get_first_heading($item['id'], false); } } // finally add the item $data[] = $item; return $return; }
/** * This function inserts a 1x1 pixel gif which in reality * is the indexer function. * * Should be called somewhere at the very end of the main.php * template */ function tpl_indexerWebBug() { global $ID; global $INFO; if (!$INFO['exists']) { return false; } if (isHiddenPage($ID)) { return false; } //no need to index hidden pages $p = array(); $p['src'] = DOKU_BASE . 'lib/exe/indexer.php?id=' . rawurlencode($ID) . '&' . time(); $p['width'] = 1; $p['height'] = 1; $p['alt'] = ''; $att = buildAttributes($p); print "<img {$att} />"; return true; }
/** * Returns the backlinks for a given page * * Uses the metadata index. */ function ft_backlinks($id) { $result = array(); $result = idx_get_indexer()->lookupKey('relation_references', $id); if (!count($result)) { return $result; } // check ACL permissions foreach (array_keys($result) as $idx) { if (isHiddenPage($result[$idx]) || auth_quickaclcheck($result[$idx]) < AUTH_READ || !page_exists($result[$idx], '', false)) { unset($result[$idx]); } } sort($result); return $result; }
function getContent(&$exp) { $rdf = '<' . $this->_type . " rdf:about=\"" . clean($this->_url, true) . "\">\n"; if ($this->_subject) { $rdf .= "\t<dc:title>" . clean($this->_subject) . "</dc:title>\n"; // if(strcmp($this->_has_container, 'http://en.wikipedia.org')===0) // $rdf .= "\t<foaf:primaryTopic rdf:resource=\"".clean('http://dbpedia.org/resource/'.$this->_subject)."\"/>\n"; } $creator_name = null; if (count($this->_contributors) > 0) { foreach ($this->_contributors as $cont_id => $cont_name) { if (!isset($this->_creator['sioc:modifier']) || $this->_creator['sioc:modifier'] != $cont_id) { $rdf .= "\t<sioc:has_modifier rdf:resource=\"" . normalizeUri($exp->siocURL('user', $cont_id)) . "\" rdfs:label=\"" . clean($cont_name) . "\"/>\n"; } } if (isset($this->_contributors[$this->_creator['sioc:modifier']])) { $creator_name = 'rdfs:label="' . clean($this->_contributors[$this->_creator['sioc:modifier']]) . '"'; } } if (is_array($this->_creator)) { // if ($this->_creator['foaf:maker']) // $rdf .= "\t<foaf:maker rdf:resource=\"".clean($this->_creator['foaf:maker'])."\"/>\n"; if ($this->_creator['sioc:modifier']) { if ($this->_is_creator === false) { $rdf .= "\t<sioc:has_modifier rdf:resource=\"" . normalizeUri($exp->siocURL('user', $this->_creator['sioc:modifier'])) . "\" {$creator_name}/>\n"; } if ($this->_is_creator === true) { $rdf .= "\t<sioc:has_creator rdf:resource=\"" . normalizeUri($exp->siocURL('user', $this->_creator['sioc:modifier'])) . "\" {$creator_name}/>\n"; } } } if ($this->_created) { $rdf .= "\t<dcterms:created>" . $this->_created . "</dcterms:created>\n"; } if ($this->_modified) { $rdf .= "\t<dcterms:modified>" . $this->_modified . "</dcterms:modified>\n"; } if ($this->_has_space) { $rdf .= "\t<sioc:has_space rdf:resource=\"" . clean($this->_has_space, true) . "\" />\n"; // TODO: rdfs:label } if ($this->_has_container) { $rdf .= "\t<sioc:has_container rdf:resource=\"" . normalizeUri($exp->siocURL('container', $this->_has_container)) . "\" />\n"; // TODO: rdfs:label } if ($this->_content) { $rdf .= "\t<sioc:content><![CDATA[" . pureContent($this->_content) . "]]></sioc:content>\n"; } if ($this->_content_encoded) { $rdf .= "\t<content:encoded><![CDATA[" . $this->_content_encoded . "]]></content:encoded>\n"; } /* if(is_array($this->_topics)) { foreach($this->_topics as $topic=>$url) { $rdf .= "\t<sioc:topic>\n"; $rdf .= "\t\t<sioct:Category rdf:about=\"" . clean($url) ."\">\n"; $rdf .= "\t\t\t<rdfs:seeAlso rdf:resource=\"" . clean('http://ws.sioc-project.org/mediawiki/mediawiki.php?wiki='.$url); if ($this->_api) $rdf .= clean("&api=" . $this->_api); $rdf .= "\"/>\n"; $rdf .= "\t\t</sioct:Category>\n"; $rdf .= "\t</sioc:topic>\n"; } } */ if (is_array($this->_links) && count($this->_links) > 0) { foreach ($this->_links as $link_id => $link_exists) { if ($link_exists && !isHiddenPage($link_id)) { $rdf .= "\t<sioc:links_to rdf:resource=\"" . normalizeUri($exp->siocURL('post', $link_id)) . "\"/>\n"; // TODO: rdfs:label } } } if (count($this->_backlinks) > 0) { foreach ($this->_backlinks as $link_id) { if (!isHiddenPage($link_id)) { $rdf .= "\t<dcterms:isReferencedBy rdf:resource=\"" . normalizeUri($exp->siocURL('post', $link_id)) . "\"/>\n"; // TODO: rdfs:label } } } /* if(is_array($this->_ext_links)) { foreach($this->_ext_links as $label=>$url) { $rdf .= "\t<sioc:links_to rdf:resource=\"" . clean($url) ."\"/>\n"; } } */ if ($this->_previous_version) { $rdf .= "\t<sioc:previous_version rdf:resource=\"" . normalizeUri($exp->siocURL('post', $this->_id . $exp->_urlseparator . 'rev' . $exp->_urlequal . $this->_previous_version)) . "\"/>\n"; // TODO: rdfs:label /* If there is support for inference and transitivity the following is not needed */ $rdf .= "\t<sioc:earlier_version rdf:resource=\"" . normalizeUri($exp->siocURL('post', $this->_id . $exp->_urlseparator . 'rev' . $exp->_urlequal . $this->_previous_version)) . "\"/>\n"; // TODO: rdfs:label } if ($this->_next_version) { $rdf .= "\t<sioc:next_version rdf:resource=\"" . normalizeUri($exp->siocURL('post', $this->_id . $exp->_urlseparator . 'rev' . $exp->_urlequal . $this->_next_version)) . "\"/>\n"; // TODO: rdfs:label /* If there is support for inference and transitivity the following is not needed */ $rdf .= "\t<sioc:later_version rdf:resource=\"" . normalizeUri($exp->siocURL('post', $this->_id . $exp->_urlseparator . 'rev' . $exp->_urlequal . $this->_next_version)) . "\"/>\n"; // TODO: rdfs:label } if ($this->_latest_version) { $rdf .= "\t<sioc:latest_version rdf:resource=\"" . normalizeUri($exp->siocURL('post', $this->_id)) . "\"/>\n"; // TODO: rdfs:label } /* if($this->_has_discussion && (strpos($this->_has_discussion, 'Talk:Talk:') == FALSE)) { $rdf .= "\t<sioc:has_discussion>\n"; $rdf .= "\t\t<sioct:WikiArticle rdf:about=\"" . clean($this->_has_discussion) ."\">\n"; $rdf .= "\t\t\t<rdfs:seeAlso rdf:resource=\"" . clean('http://ws.sioc-project.org/mediawiki/mediawiki.php?wiki='.$this->_has_discussion); if ($this->_api) $rdf .= clean("&api=" . $this->_api); $rdf .= "\"/>\n"; $rdf .= "\t\t</sioct:WikiArticle>\n"; $rdf .= "\t</sioc:has_discussion>\n"; } */ /* if($this->_redirpage) { $rdf .= "\t<owl:sameAs rdf:resource=\"" . clean($this->_redirpage) ."\"/>\n"; $rdf .= "\t<rdfs:seeAlso rdf:resource=\"" . clean('http://ws.sioc-project.org/mediawiki/mediawiki.php?wiki='.$this->_redirpage); if ($this->_api) $rdf .= clean("&api=" . $this->_api); $rdf .= "\"/>\n"; } */ $rdf .= "</" . $this->_type . ">\n"; return $rdf; }