1<?php
2/**
3 * IPGroup Plugin
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     Sascha Bendix <sascha.bendix@localroot.de>
7 * @author     Marcel Pennewiss <opensource@pennewiss.de>
8 * @author     Peter Grosse <pegro@fem-net.de>
9 * @author     Jonas Licht <jonas.licht@fem.tu-ilmenau.de>
10 */
11
12if(!defined('DOKU_INC')) die();
13if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
14
15require_once(DOKU_PLUGIN.'action.php');
16
17class action_plugin_ipgroup extends DokuWiki_Action_Plugin {
18
19    /**
20     * Register event handlers
21     */
22    public function register(Doku_Event_Handler $controller) {
23		$controller->register_hook('AUTH_ACL_CHECK', 'BEFORE', $this, 'start');
24    }
25
26    function start(&$event, $param) {
27		// get remote ip when user is using a proxy
28		$ip = clientIP(true);
29
30		// read config file or create
31		$filecontent = @file(DOKU_CONF.'ipgroup.conf', FILE_SKIP_EMPTY_LINES);
32		if ($filecontent === false) { $filecontent = array(); }
33
34		// check current ip against each network-definition
35		foreach ($filecontent as $line) {
36			// seperate network and group and trim spaces
37			list($network,$group) = explode(';', $line);
38			$network = rtrim($network);
39			$group = rtrim($group);
40
41			// seperate cidr-suffix from network
42			$network_bits = substr($network,strpos($network,'/')+1);
43
44			// only go further if the acces is done via the same ip version then the network we are currently looking at
45			if (filter_var($network_address,FILTER_VALIDATE_IP,FILTER_FLAG_IPV4) == filter_var($ip,FILTER_VALIDATE_IP,FILTER_FLAG_IPV4)
46				|| (filter_var($network_address,FILTER_VALIDATE_IP,FILTER_FLAG_IPV6) == filter_var($ip,FILTER_VALIDATE_IP,FILTER_FLAG_IPV6))) {
47
48				// check if ip matches network
49				if ($this->ip2pton($ip."/".$network_bits) === $this->ip2pton($network)) {
50				    // add group to list
51				    $event->data['groups'][] = $group;
52				}
53			}
54		}
55    }
56
57    /**
58     * calc ip-adress to in_addr-representation
59     * @link http://www.php.net/manual/de/function.inet-pton.php#93501 source and idea
60     */
61    function ip2pton($ipaddr) {
62
63        // Strip out the netmask, if there is one.
64        $cx = strpos($ipaddr, '/');
65        if ($cx)
66        {
67            $subnet = (int)(substr($ipaddr, $cx+1));
68            $ipaddr = substr($ipaddr, 0, $cx);
69        }
70        else $subnet = null; // No netmask present
71
72        // Convert address to packed format
73        $addr = inet_pton($ipaddr);
74
75        // Convert the netmask
76        if (is_integer($subnet))
77        {
78            // Maximum netmask length = same as packed address
79            $len = 8*strlen($addr);
80            if ($subnet > $len) $subnet = $len;
81
82            // Create a hex expression of the subnet mask
83            $mask  = str_repeat('f', $subnet>>2);
84            switch($subnet & 3)
85            {
86                case 3: $mask .= 'e'; break;
87                case 2: $mask .= 'c'; break;
88                case 1: $mask .= '8'; break;
89            }
90            $mask = str_pad($mask, $len>>2, '0');
91
92            // Packed representation of netmask
93            $mask = pack('H*', $mask);
94        }
95
96        // Return logical and of addr and mask
97	    return ($addr & $mask);
98    }
99}
100