예제 #1
0
function dw_get_pages($dir)
{
    static $trunclen = null;
    if (!$trunclen) {
        global $conf;
        $trunclen = strlen($conf['datadir'] . ':');
    }
    if (!is_dir($dir)) {
        fwrite(STDERR, "Unable to read directory {$dir}\n");
        exit(1);
    }
    $pages = array();
    $dh = opendir($dir);
    while (false !== ($entry = readdir($dh))) {
        $status = dw_dir_filter($entry, $dir);
        if ($status == DW_DIR_CONTINUE) {
            continue;
        } else {
            if ($status == DW_DIR_NS) {
                $pages = array_merge($pages, dw_get_pages($dir . '/' . $entry));
            } else {
                $page = array('id' => pathID(substr($dir . '/' . $entry, $trunclen)), 'file' => $dir . '/' . $entry);
                $pages[] = $page;
            }
        }
    }
    closedir($dh);
    return $pages;
}
예제 #2
0
 /**
  * Search for internal wiki links in page $file
  */
 function orph_Check_InternalLinks(&$data, $base, $file, $type, $lvl, $opts)
 {
     global $conf;
     define('LINK_PATTERN', '%\\[\\[([^\\]|#]*)(#[^\\]|]*)?\\|?([^\\]]*)]]%');
     if (!preg_match("/.*\\.txt\$/", $file)) {
         return;
     }
     $currentID = pathID($file);
     $currentNS = getNS($currentID);
     if ($conf['allowdebug']) {
         echo sprintf("<p><b>%s</b>: %s</p>\n", $file, $currentID);
     }
     // echo "  <!-- checking file: $file -->\n";
     $body = @file_get_contents($conf['datadir'] . $file);
     // ignores entries in <nowiki>, %%, <code> and emails with @
     foreach (array('/<nowiki>.*?<\\/nowiki>/', '/%%.*?%%/', '@<code[^>]*?>.*?<\\/code>@siu', '@<file[^>]*?>.*?<\\/file>@siu') as $ignored) {
         $body = preg_replace($ignored, '', $body);
     }
     $links = array();
     preg_match_all(LINK_PATTERN, $body, $links);
     foreach ($links[1] as $link) {
         if ($conf['allowdebug']) {
             echo sprintf("--- Checking %s<br />\n", $link);
         }
         if (0 < strlen(ltrim($link)) and !preg_match('/^[a-zA-Z0-9\\.]+>{1}.*$/u', $link) and !preg_match('/^\\\\\\\\[\\w.:?\\-;,]+?\\\\/u', $link) and !preg_match('#^([a-z0-9\\-\\.+]+?)://#i', $link) and !preg_match('<' . PREG_PATTERN_VALID_EMAIL . '>', $link) and !preg_match('!^#.+!', $link)) {
             $pageExists = false;
             resolve_pageid($currentNS, $link, $pageExists);
             if ($conf['allowdebug']) {
                 echo sprintf("---- link='%s' %s ", $link, $pageExists ? 'EXISTS' : 'MISS');
             }
             if (strlen(ltrim($link)) > 0 and !auth_quickaclcheck($link) < AUTH_READ) {
                 // should be visible to user
                 //echo "      <!-- adding $link -->\n";
                 if ($conf['allowdebug']) {
                     echo ' A_LINK';
                 }
                 $link = utf8_strtolower($link);
                 $this->orph_handle_link($data, $link);
             } else {
                 if ($conf['allowdebug']) {
                     echo ' EMPTY_OR_FORBIDDEN';
                 }
             }
         } else {
             if ($conf['allowdebug']) {
                 echo ' NOT_INTERNAL';
             }
         }
         if ($conf['allowdebug']) {
             echo "<br />\n";
         }
     }
     // end of foreach link
 }
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;
}
예제 #4
0
/**
 * function for the search callback
 */
function search_discussionpages(&$data, $base, $file, $type, $lvl, $opts)
{
    global $conf;
    if ($type == 'd') {
        return true;
    }
    // recurse into directories
    if (!preg_match('#' . preg_quote('/' . DISCUSSION_NS . '/', '#') . '#u', $file)) {
        return false;
    }
    if (!preg_match('#\\.txt$#', $file)) {
        return false;
    }
    $id = pathID(str_replace(DISCUSSION_NS . '/', '', $file));
    $data[] = array('id' => $id, 'old' => $conf['datadir'] . $file, 'new' => metaFN($id, '.comments'));
    return true;
}
예제 #5
0
파일: search.php 프로젝트: Harvie/dokuwiki
/**
 * 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;
}
function orph_search_wanted(&$data, $base, $file, $type, $lvl, $opts)
{
    if ($type == 'd') {
        return true;
        // recurse all directories, but we don't store namespaces
    }
    if (!preg_match("/.*\\.txt\$/", $file)) {
        // Ignore everything but TXT
        return true;
    }
    // search the body of the file for links
    // dae mod
    // orph_Check_InternalLinks(&$data,$base,$file,$type,$lvl,$opts);
    orph_Check_InternalLinks($data, $base, $file, $type, $lvl, $opts);
    // get id of this file
    $id = pathID($file);
    //check ACL
    if (auth_quickaclcheck($id) < AUTH_READ) {
        return false;
    }
    // try to avoid making duplicate entries for forms and pages
    $item =& $data["{$id}"];
    if (isset($item)) {
        // This item already has a member in the array
        // Note that the file search found it
        $item['exists'] = true;
    } else {
        // Create a new entry
        $data["{$id}"] = array('exists' => true, 'links' => 0);
    }
    return true;
}
예제 #7
0
/**
 * fulltext search helper
 * searches a text file with a given regular expression
 * no ACL checks are performed. This have to be done by
 * the caller if necessary.
 *
 * @param array  $data  reference to array for results
 * @param string $base  base directory
 * @param string $file  file name to search in
 * @param string $reg   regular expression to search for
 * @param array  $words words that should be marked in the results
 *
 * @author  Andreas Gohr <*****@*****.**>
 * @author  Matthias Grimm <*****@*****.**>
 *
 * @deprecated - fulltext indexer is used instead
 */
function search_regex(&$data, $base, $file, $reg, $words)
{
    //get text
    $text = io_readfile($base . '/' . $file);
    //lowercase text (u modifier does not help with case)
    $lctext = utf8_strtolower($text);
    //do the fulltext search
    $matches = array();
    if ($cnt = preg_match_all('#' . $reg . '#usi', $lctext, $matches)) {
        //this is not the best way for snippet generation but the fastest I could find
        $q = $words[0];
        //use first word for snippet creation
        $p = utf8_strpos($lctext, $q);
        $f = $p - 100;
        $l = utf8_strlen($q) + 200;
        if ($f < 0) {
            $f = 0;
        }
        $snippet = '<span class="search_sep"> ... </span>' . htmlspecialchars(utf8_substr($text, $f, $l)) . '<span class="search_sep"> ... </span>';
        $mark = '(' . join('|', $words) . ')';
        $snippet = preg_replace('#' . $mark . '#si', '<strong class="search_hit">\\1</strong>', $snippet);
        $data[] = array('id' => pathID($file), 'count' => preg_match_all('#' . $mark . '#usi', $lctext, $matches), 'poswords' => join(' ', $words), 'snippet' => $snippet);
    }
    return true;
}
예제 #8
0
 /**
  * Expire the renderer cache of archive pages whenever a page is updated or a comment or linkback is added
  *
  * @author Michael Hamann <*****@*****.**>
  */
 function handle_cache(Doku_Event $event, $params)
 {
     global $conf;
     /** @var cache_parser $cache */
     $cache = $event->data;
     if (!in_array($cache->mode, array('xhtml', 'metadata'))) {
         return;
     }
     $page = $cache->page;
     // try to extract the page id from the file if possible
     if (empty($page)) {
         if (strpos($cache->file, $conf['datadir']) === 0) {
             $page = pathID(substr($cache->file, strlen($conf['datadir']) + 1));
         } else {
             return;
         }
     }
     $meta = p_get_metadata($page, 'plugin_blog');
     if ($meta === null) {
         return;
     }
     if (isset($meta['purgefile_cache'])) {
         $cache->depends['files'][] = $conf['cachedir'] . '/purgefile';
         $cache->depends['files'][] = $conf['metadir'] . '/_comments.changes';
         $cache->depends['files'][] = $conf['metadir'] . '/_linkbacks.changes';
     }
     // purge the cache when a page is listed that the current user can't access
     if (isset($meta['archive_pages'])) {
         foreach ($meta['archive_pages'] as $page) {
             if (auth_quickaclcheck($page) < AUTH_READ) {
                 $cache->depends['purge'] = true;
                 return;
             }
         }
     }
 }
예제 #9
0
 /**
  * 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;
 }
예제 #10
0
 /**
  * Handle the cache events, it looks if a page needs to be rewritten so it can expire the cache of the page
  *
  * @param Doku_Event $event The even object
  * @param mixed      $param Optional parameters (not used)
  */
 function handle_cache(Doku_Event $event, $param)
 {
     global $conf;
     /** @var $cache cache_parser */
     $cache = $event->data;
     $id = $cache->page;
     if (!$id) {
         // try to reconstruct the id from the filename
         $path = $cache->file;
         if (strpos($path, $conf['datadir']) === 0) {
             $path = substr($path, strlen($conf['datadir']) + 1);
             $id = pathID($path);
         }
     }
     if ($id) {
         /** @var helper_plugin_move_rewrite $helper */
         $helper = $this->loadHelper('move_rewrite');
         if (!is_null($helper)) {
             $meta = $helper->getMoveMeta($id);
             if ($meta && ($meta['pages'] || $meta['media'])) {
                 $file = wikiFN($id, '', false);
                 if (is_writable($file)) {
                     $cache->depends['purge'] = true;
                 } else {
                     // FIXME: print error here or fail silently?
                     msg('Error: Page ' . hsc($id) . ' needs to be rewritten because of page renames but is not writable.', -1);
                 }
             }
         }
     }
 }
예제 #11
0
 protected function get_pages($dir)
 {
     static $trunclen = null;
     if (!$trunclen) {
         global $conf;
         $trunclen = strlen($conf['datadir'] . ':');
     }
     if (!is_dir($dir)) {
         throw new DokuCLI_Exception("Unable to read directory {$dir}");
     }
     $pages = array();
     $dh = opendir($dir);
     while (false !== ($entry = readdir($dh))) {
         $status = $this->dir_filter($entry, $dir);
         if ($status == WantedPagesCLI::DIR_CONTINUE) {
             continue;
         } else {
             if ($status == WantedPagesCLI::DIR_NS) {
                 $pages = array_merge($pages, $this->get_pages($dir . '/' . $entry));
             } else {
                 $page = array('id' => pathID(substr($dir . '/' . $entry, $trunclen)), 'file' => $dir . '/' . $entry);
                 $pages[] = $page;
             }
         }
     }
     closedir($dh);
     return $pages;
 }
예제 #12
0
파일: action.php 프로젝트: neutrinog/Door43
 /**
  * Handle the cache events, it looks if a page needs to be rewritten so it can expire the cache of the page
  *
  * @param Doku_Event $event The even object
  * @param mixed      $param Optional parameters (not used)
  */
 function handle_cache(Doku_Event $event, $param) {
     global $conf;
     /** @var $cache cache_parser */
     $cache = $event->data;
     $id = $cache->page;
     if (!$id) {
         // try to reconstruct the id from the filename
         $path = $cache->file;
         if (strpos($path, $conf['datadir']) === 0) {
             $path = substr($path, strlen($conf['datadir'])+1);
             $id = pathID($path);
         }
     }
     if ($id) {
         $meta = p_get_metadata($id, 'plugin_move', METADATA_DONT_RENDER);
         if ($meta && (isset($meta['moves']) || isset($meta['media_moves']))) {
             $file = wikiFN($id, '', false);
             if (is_writable($file))
                 $cache->depends['purge'] = true;
             else // FIXME: print error here or fail silently?
                 msg('Error: Page '.hsc($id).' needs to be rewritten because of page renames but is not writable.', -1);
         }
     }
 }
예제 #13
0
 /**
  * search callback function
  *
  * filter out pages which can't be approved by the current user
  * then check if they need approving
  */
 function _search_helper(&$data, $base, $file, $type, $lvl, $opts)
 {
     $ns = $opts[0];
     $valid_ns = $opts[1];
     $invalid_ns = $opts[2];
     if ($type == 'd') {
         return $this->hlp->in_sub_namespace($valid_ns, $ns . ':' . str_replace('/', ':', $file));
     }
     if (!preg_match('#\\.txt$#', $file)) {
         return false;
     }
     $id = pathID($ns . $file);
     if (!$this->hlp->in_namespace($valid_ns, $id)) {
         return false;
     }
     if ($this->hlp->in_namespace($invalid_ns, $id)) {
         return false;
     }
     if (auth_quickaclcheck($id) < AUTH_DELETE) {
         return false;
     }
     $meta = $this->hlp->getMeta($id);
     if ($this->hlp->isCurrentRevisionApproved($id)) {
         // Already approved
         return false;
     }
     $data[] = array($id, $meta['approval'], $meta['last_change']['date']);
     return false;
 }
 /**
  * Just lists all documents
  *
  * $opts['depth']   recursion level, 0 for all
  * $opts['hash']    do md5 sum of content?
  * $opts['skipacl'] list everything regardless of ACL
  *
  * @param $data
  * @param $base
  * @param $file
  * @param $type
  * @param $lvl
  * @param $opts
  * @return bool
  */
 public static function save_search_allpages(&$data, $base, $file, $type, $lvl, $opts)
 {
     if (!empty($opts['depth'])) {
         $parts = explode('/', ltrim($file, '/'));
         if ($type == 'd' && count($parts) >= $opts['depth'] || $type != 'd' && count($parts) > $opts['depth']) {
             return false;
             // depth reached
         }
     }
     //we do nothing with directories
     if ($type == 'd') {
         return true;
     }
     //only search txt files
     if (substr($file, -4) != '.txt') {
         return true;
     }
     $pathId = pathID($file);
     if (!$opts['skipacl'] && auth_quickaclcheck($pathId) < AUTH_READ) {
         return false;
     }
     file_put_contents(self::$tempFileName, "{$pathId}\n", FILE_APPEND);
     self::$totalPagesToIndex++;
     return true;
 }