1<?php
2/**
3 * Cf licence informations in README
4 */
5
6// must be run within Dokuwiki
7if(!defined('DOKU_INC'))
8	die('yeurk!');
9
10if(!defined('DOKU_PLUGIN'))
11	define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/');
12
13require_once(DOKU_PLUGIN . 'admin.php');
14
15
16/**
17 * All DokuWiki plugins to extend the admin function
18 * need to inherit from this class
19 */
20class admin_plugin_tokenbucketauth extends DokuWiki_Admin_Plugin
21{
22	/**
23	 * access for managers
24	 */
25	function forAdminOnly()
26	{
27		return false;
28	}
29
30	/**
31	 * return sort order for position in admin menu
32	 */
33	function getMenuSort()
34	{
35		return 42;
36	}
37
38	/**
39	 * handle user request
40	 */
41	function handle()
42	{
43		global $conf;
44
45		if(empty($_REQUEST['tba__delete_ip']))
46			return;
47
48		if(empty($_REQUEST['delip']) || !is_array($_REQUEST['delip']))
49			return;
50
51		/* Get the IP address */
52		$ip = array_shift(array_keys($_REQUEST['delip']));
53
54		$lockf = $conf['cachedir'] . '/' . $this->getConf('tba_lockfile');
55		$banned_f  = $conf['cachedir'] . '/' . $this->getConf('tba_block_file');
56
57		/* Lock the file for writing */
58		$lockfh = fopen($lockf, 'w', false);
59
60		if($lockfh === false)
61			return;
62
63		if(flock($lockfh, LOCK_EX) === false)
64		{
65			fclose($lockfh);
66			return;
67		}
68
69		/* Open the file to search for the $ip to delete */
70		$content = file_get_contents($banned_f);
71
72		if(empty($content))
73		{
74			flock($lockfh, LOCK_UN);
75			fclose($lockfh);
76
77			msg(sprintf($this->getLang('del_ipnotfound'), $ip), -1);
78			return;
79		}
80		else
81			$blocked = @unserialize($content);
82
83		/* Deal with the case of unserialize() failing */
84		if($blocked === false || !is_array($blocked))
85		{
86			flock($lockfh, LOCK_UN);
87			fclose($lockfh);
88			return;
89		}
90
91		if(isset($blocked[$ip]))
92		{
93			/* Remove the banned IP */
94			unset($blocked[$ip]);
95
96			/* Save the blocked-IP file */
97			io_saveFile($banned_f, serialize($blocked));
98
99			/* Remove any occurrence of this IP address in the tracker file */
100			$track_f = $conf['cachedir'] . '/' . $this->getConf('tba_iptime_file');
101			$content = file_get_contents($track_f);
102			$user_tracker = null;
103
104			if(empty($content))
105				$users_tracker = array();
106			else
107				$users_tracker = @unserialize($content);
108
109			if($users_tracker === false)
110				$users_tracker = array();
111
112			if(isset($users_tracker[$ip]))
113				unset($users_tracker[$ip]);
114
115			io_saveFile($track_f, serialize($users_tracker));
116
117			msg(sprintf($this->getLang('del_success'), $ip), 1);
118		}
119		else
120			msg(sprintf($this->getLang('del_ipnotfound'), $ip), -1);
121
122		flock($lockfh, LOCK_UN);
123		fclose($lockfh);
124	}
125
126	/**
127	 * output appropriate html
128	 */
129	function html()
130	{
131		global $conf;
132
133		$banned_f = $conf['cachedir'] . '/' . $this->getConf('tba_block_file');
134		$bans = @file_get_contents($banned_f);
135
136		if(empty($bans))
137			$bans = array();
138		else
139			$bans = @unserialize($bans);
140
141		/* Deal with the case of unserialize() failing */
142		if($bans === false)
143			$bans = array();
144
145		/* Get the current time once and for all */
146		$curr_time = time();
147		$ban_time  = $this->getConf('tba_block_time');
148
149		/* Remove IP which have their ban expired */
150		$new_bans = array();
151		foreach($bans as $ip => $block_timestamp)
152		{
153			if($block_timestamp + $ban_time < $curr_time)
154				continue;
155
156			$new_bans[$ip] = $block_timestamp;
157		}
158		$bans = $new_bans;
159
160		/* Now fill the admin panel */
161		echo $this->locale_xhtml('admin_intro');
162
163		echo '<form method="post" action="">';
164		echo '<table class="inline" width="100%">';
165		echo '<tr>';
166		echo '<th>'.$this->getLang('ip').'</th>';
167		echo '<th>'.$this->getLang('host').'</th>';
168		echo '<th>'.$this->getLang('date').'</th>';
169		echo '<th>'.$this->getLang('del').'</th>';
170		echo '</tr>';
171
172		if(!empty($bans) && is_array($bans))
173		{
174			foreach($bans as $ip => $block_timestamp)
175			{
176				$host = @gethostbyaddr($ip);
177				if($host === false || $host === $ip)
178					$host = '?';
179
180				echo '<tr>';
181				echo '<td>'.$ip.'</td>';
182				echo '<td>'.hsc($host).'</td>';
183				echo '<td>'.strftime($conf['dformat'], $block_timestamp).'</td>';
184				echo '<td><input type="submit" name="delip['.$ip.']" value="'.hsc($this->getLang('del')).'" class="button" /></td>';
185				echo '</tr>';
186			}
187		}
188		else
189		{
190			echo '<tr>';
191			echo '<td colspan="4" style="text-align:center; font-style: italic">' . hsc($this->getLang('noban')) . '</td>';
192			echo '</tr>';
193		}
194		echo '</table>';
195		echo '<input type="hidden" name="tba__delete_ip" value="1" />';
196		echo '</form>';
197	}
198}
199