1<?php
2
3/**
4 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
5 * @author     Andreas Gohr <andi@splitbrain.org>
6 */
7class action_plugin_ipban extends DokuWiki_Action_Plugin
8{
9
10    /**
11     * register the eventhandlers and initialize some options
12     */
13    public function register(Doku_Event_Handler $controller)
14    {
15
16        $controller->register_hook('DOKUWIKI_STARTED',
17            'BEFORE',
18            $this,
19            'handle_start',
20            array());
21    }
22
23    /**
24     * Do the magic
25     *
26     * @param Doku_Event $event
27     * @param $param
28     */
29    public function handle_start(Doku_Event $event, $param)
30    {
31        global $conf;
32
33        $bans = @file($conf['cachedir'] . '/ipbanplugin.txt');
34        $client = clientIP(true);
35        if (!is_array($bans)) return;
36
37        // if the client isn't banned, we're done
38        $banreason = $this->isBanned($client, $bans);
39        if (!$banreason) return;
40
41        // prepare template
42        $text = $this->locale_xhtml('banned');
43        $text .= vsprintf('<p>' . $this->getLang('banned') . '</p>', array_map('hsc', $banreason));
44        $title = $this->getLang('denied');
45
46        // output
47        http_status(403, 'Forbidden');
48        echo '<!DOCTYPE html>';
49        echo '<html>';
50        echo "<head><title>$title</title></head>";
51        echo '<body style="font-family: Arial, sans-serif">';
52        echo '<div style="width:60%; margin: auto; background-color: #fcc; border: 1px solid #faa; padding: 0.5em 1em;">';
53        echo $text;
54        echo '</div>';
55        echo '</body>';
56        echo '</html>';
57        exit;
58    }
59
60    /**
61     * Check if the given client IP is in the list of ban lines
62     *
63     * @param string $client IP of the client
64     * @param string[] $banconf List of ban lines
65     * @return false|array false or ban info [ip, date, reason]
66     */
67    protected function isBanned($client, $banconf)
68    {
69        require_once(__DIR__ . '/ip-lib/ip-lib.php');
70
71        $ip = \IPLib\Factory::addressFromString($client);
72        foreach ($banconf as $ban) {
73            list($range, $dt, /*user*/, $reason) = explode("\t", trim($ban));
74            $ipRange = \IPLib\Factory::rangeFromString($range);
75            if($ipRange === null) continue;
76            if ($ip->matches($ipRange)) {
77                return [
78                    $ip->toString(),
79                    dformat($dt),
80                    $reason,
81                ];
82            }
83        }
84
85        return false;
86    }
87}
88