1<?php
2// must be run within DokuWiki
3if(!defined('DOKU_INC')) die();
4
5if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
6require_once DOKU_PLUGIN.'syntax.php';
7
8/**
9 * Plugin maps drive letters to a unc path.
10 */
11class syntax_plugin_uncmap extends DokuWiki_Syntax_Plugin {
12
13    /**
14     * stores an array with the mappings.
15     *
16     * format is
17     *   letter => path
18     */
19    var $pathes = array();
20
21    /**
22     * the path to the mounted fileserver.
23     *
24     * this is used for linkchecking. if the path is null the linkcheck is disabled.
25     */
26    var $fileserver = array(0 => null);
27
28    /**
29     * load the mapping array.
30     */
31    function syntax_plugin_uncmap() {
32
33        $lines = @file( dirname(__FILE__) . '/conf/mapping.php' );
34        if ( $lines ) {
35            $lines_fs = array();
36            $lines_pathes = array();
37            foreach ($lines as $line) {
38                if (preg_match('/[a-z]/',strtolower($line[0])) == 1) {
39                    $letter = $line[0];
40                    $line = substr($line,1);
41                    $line = trim($line);
42                    if (empty($line)) continue;
43                    $delim = strpos($line,' ');
44                    if ($delim === false){
45                        $lines_pathes[] = implode(' ',array($letter,$line));
46                        $lines_fs[] = implode(' ',array($letter,'default'));
47                    } else {
48                        $path = substr($line,0,$delim);
49                        $fs = substr($line,$delim);
50                        $fs = trim($fs);
51                        $lines_pathes[] = implode(' ',array($letter,$path));
52                        $lines_fs[] = implode(' ',array($letter,$fs));
53                    }
54                }
55            }
56
57            $this->pathes = linesToHash($lines_pathes);
58            $this->fileserver[0] = $this->getConf('fileserver');
59            $this->fileserver = $this->fileserver + linesToHash($lines_fs);
60            foreach ($this->fileserver as $letter => $fs) {
61                if($fs !== null && file_exists($fs)) {
62
63                    $fs = str_replace('\\', '/', $fs);
64                    $fs = rtrim($fs, '/');
65                    if(substr($fs, -1) == '/') {
66                        $fs = substr($fs, 0, -1);
67                    }
68                    $this->fileserver[$letter] = $fs;
69                } elseif ($this->fileserver[0] === null || !file_exists($this->fileserver[0])){
70                    $this->fileserver[$letter] = null;
71                } else {
72                    $this->fileserver[$letter] = $this->fileserver[0];
73                }
74            }
75        }
76    }
77
78    /**
79     * syntax type is formating
80     */
81    function getType() { return 'formatting'; }
82
83    /**
84     * a very important plugin ;-)
85     */
86    function getSort() { return 282; }
87
88    /**
89     * connect to the renderer.
90     */
91    function connectTo($mode) {
92        $letters = implode('',array_keys($this->pathes));
93        if($letters !== '') {
94            $this->Lexer->addSpecialPattern('\[\[[' . strtolower($letters) . strtoupper($letters) . ']{1}\:[\\\/]{1}.+?\]\]', $mode, 'plugin_uncmap');
95        }
96    }
97
98    /**
99     * review the given url.
100     */
101    function handle($match, $state, $pos, Doku_Handler $handler) {
102
103        // trim [[ and ]]
104        $match = substr($match,2,-2);
105
106        // remove surrounding whitespaces
107        $match = trim($match);
108
109        // get the drive letter in lower case
110        $letter = strtolower($match[0]);
111        $return = array();
112        $return['letter'] = $letter;
113        // if there is a mapping for the drive letter we have work to do
114        if ($this->pathes[$letter]) {
115            $titlepos = strpos($match,'|');
116            if ($titlepos !== false){
117                $title = substr($match,$titlepos+1);
118                $match = substr($match,0,$titlepos);
119                $return['title'] = $title;
120            } else {
121                $return['title'] = null;
122            }
123            // get the mapping path
124            $path = $this->pathes[$letter];
125            $match = substr($match, 1);
126
127            $match = str_replace('/','\\',$match);
128
129            // ensure it is a real path
130            if (substr($match,0,2) == ':\\') {
131
132                // build windows share link
133                $new = $path;
134                if (substr($path,-1) != '\\') $new .= '\\';
135                $new .=  substr($match,2);
136            }
137            $return['url'] = $new;
138        }
139
140        return $return;
141    }
142
143    /**
144     * displays the link.
145     */
146    function render($mode, Doku_Renderer $renderer, $data) {
147        if($mode == 'xhtml'){
148
149            // check if there is a link and give it to the renderer
150            if (!empty($data['url'])) {
151                $renderer->windowssharelink($data['url'], $data['title']);
152
153                // check if the linked file exists on the fileserver and set the class accordingly
154                $data['exists'] = $this->checkLink($data);
155                if ($data['exists'] == 1) {
156                    $this->replaceLinkClass($renderer,'wikilink1');
157                } elseif ($data['exists'] == -1) {
158                    $this->replaceLinkClass($renderer,'wikilink2');
159                }
160            }
161        }
162        return false;
163    }
164
165    /**
166     * checks if the link exists on the server.
167     */
168    function checkLink($data) {
169        if (!$this->fileserver[$data['letter']]) {
170            return null;
171        }
172
173        $data['url'] = str_replace('\\','/',$data['url']);
174        $path = preg_replace('/^\/\/[^\/]+/i',$this->fileserver[$data['letter']],$data['url']);
175
176        return file_exists($path)?1:-1;
177    }
178
179    /**
180     * @param Doku_Renderer $renderer:
181     * @param $newClass: replace the class of the windowssharelink with this value
182     */
183    function replaceLinkClass(Doku_Renderer $renderer, $newClass){
184        $ourdoc = & $renderer->doc;
185
186        //detach the link from doc
187        $linkoffset = strrpos($ourdoc,'<a ');
188        $link = substr($ourdoc, $linkoffset);
189        $ourdoc = substr($ourdoc, 0, $linkoffset);
190        $link = preg_replace('/class=\"(windows|media)\"/','class="' . $newClass . '"',$link);
191
192        $ourdoc .= $link;
193    }
194
195}
196