1<?php
2/**
3 * Plugin nspages : Displays nicely a list of the pages of a namespace
4 *
5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author  Guillaume Turri <guillaume.turri@gmail.com>
7 */
8if(!defined('DOKU_INC')) die();
9
10class namespaceFinder {
11    private $wantedNs;
12    private $isSafe;
13
14    function __construct($path){
15        $this->wantedNs = $this->computeWantedNs($path);
16        $this->sanitizeNs();
17    }
18
19    private function computeWantedNs($wantedNS){
20        global $ID;
21        $result = '';
22        if($wantedNS == '') {
23            $wantedNS = $this->getCurrentNamespace();
24        }
25        if( $this->isRelativePath($wantedNS) ) {
26            $result = getNS($ID);
27            // normalize initial dots ( ..:..abc -> ..:..:abc )
28            $wantedNS = preg_replace('/^((\.+:)*)(\.+)(?=[^:\.])/', '\1\3:', $wantedNS);
29        }
30        $result .= ':'.$wantedNS.':';
31        return $result;
32    }
33
34    private function getCurrentNamespace(){
35        return '.';
36    }
37
38    private function isRelativePath($path){
39        return $path[0] == '.';
40    }
41
42    /**
43     * Get rid of '..'.
44     * Therefore, provides a ns which passes the cleanid() function,
45     */
46    private function sanitizeNs(){
47        $ns = explode(':', $this->wantedNs);
48
49        for($i = 0; $i < count($ns); $i++) {
50            if($ns[$i] === '' || $ns[$i] === '.') {
51                array_splice($ns, $i, 1);
52                $i--;
53            } else if($ns[$i] == '..') {
54                if($i == 0) {
55                    //the first can't be '..', to stay inside 'data/pages'
56                    break;
57                } else {
58                    //simplify the path, getting rid of 'ns:..'
59                    array_splice($ns, $i - 1, 2);
60                    $i -= 2;
61                }
62            }
63        }
64
65        $this->isSafe = (count($ns) == 0 || $ns[0] != '..');
66        $this->wantedNs = implode(':', $ns);
67    }
68
69    function getWantedNs(){
70        return $this->wantedNs;
71    }
72
73    function isNsSafe(){
74        return $this->isSafe;
75    }
76
77    function getWantedDirectory(){
78        return $this->namespaceToDirectory($this->wantedNs);
79    }
80
81    static function namespaceToDirectory($ns){
82        return utf8_encodeFN(str_replace(':', '/', $ns));
83    }
84}
85