1<?php
2
3/**
4 * DokuWiki Plugin simpleforward (Action Component)
5 *
6 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
7 * @author  Michal Koutný <michal@fykos.cz>
8 */
9// must be run within Dokuwiki
10if (!defined('DOKU_INC'))
11    die();
12
13class action_plugin_simpleforward extends DokuWiki_Action_Plugin {
14
15    /**
16     * Registers a callback function for a given event
17     *
18     * @param Doku_Event_Handler $controller DokuWiki's event controller object
19     * @return void
20     */
21    public function register(Doku_Event_Handler $controller) {
22
23        $controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, 'handle_dokuwiki_started');
24    }
25
26    /**
27     * [Custom event handler which performs action]
28     *
29     * @param Doku_Event $event  event object by reference
30     * @param mixed      $param  [the parameters passed as fifth argument to register_hook() when this
31     *                           handler was registered]
32     * @return void
33     */
34    public function handle_dokuwiki_started(Doku_Event &$event, $param) {
35        global $ACT;
36        global $ID;
37        global $INFO;
38
39
40        global $conf;
41        /* Disabled by user */
42        $disableForward = !$this->getConf('enabled');
43        /* Disabled for the request */
44        $disableForward = $disableForward || $_GET['dokuwiki_simpleforward'] === '0';
45        /* Default page is not forwarded due to form actions */
46        $disableForward = $disableForward || ($this->nonemptyPath() && $ID === $conf['start']);
47        /* Dokuwiki uses 'id' as query parameter of searches
48         * (Those are probably nonexistent pages, prefer display the search results.) */
49        $disableForward = $disableForward || ($ACT === 'search');
50
51        if ($INFO['exists'] || $disableForward) {
52            return;
53        }
54
55        $basedir = $this->getConf('document_root');
56        $index = $basedir . DIRECTORY_SEPARATOR . $this->getConf('index');
57        if (!$basedir || !file_exists($index)) {
58            return;
59        }
60
61        /* Obtain filename from REQUEST_URI (note it's URL encoded) */
62        $ru = $_SERVER['REQUEST_URI'];
63        $url = "http://dummy.org$ru";
64        $urlParts = parse_url($url);
65        $path = rawurldecode($urlParts['path']);
66        $file = $basedir . DIRECTORY_SEPARATOR . $path;
67
68        unset($_GET['id']);
69
70        if (is_file($file)) {
71            if (strtolower(substr($path, -4)) == '.php') {
72                $this->forward_request($file);
73            } else {
74                $this->send_file($file);
75            }
76        } else {
77            $this->forward_request($index);
78        }
79    }
80
81    private function send_file($file) {
82        static $content = array(
83            'css' => 'text/css',
84        );
85        $ext = strtolower(substr($file, strrpos($file, '.') + 1));
86        if (isset($content[$ext])) {
87            $type = $content[$ext];
88        } else {
89            $type = mime_content_type($file);
90        }
91
92        header('Content-Type: ' . $type);
93        header('Content-Length: ' . filesize($file));
94        ob_clean();
95        flush();
96        readfile($file);
97        exit;
98    }
99
100    private function forward_request($file) {
101        @session_write_close();
102        require $file;
103        exit;
104    }
105
106    private function nonemptyPath() {
107        $parts = explode('?', $_SERVER['REQUEST_URI'], 2);
108        return $parts[0] !== DOKU_BASE;
109    }
110
111}
112
113// vim:ts=4:sw=4:et:
114