1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372:
<?php
$plugin_is_filter = 8 | CLASS_PLUGIN;
$plugin_description = gettext("Tools to block hacker access to your site.");
$plugin_author = "Stephen Billard (sbillard)";
$plugin_category = gettext('Admin');
$option_interface = 'ipBlocker';
zp_register_filter('load_theme_script', 'ipBlocker::load');
zp_register_filter('admin_allow_access', 'ipBlocker::adminGate');
zp_register_filter('admin_login_attempt', 'ipBlocker::login');
zp_register_filter('federated_login_attempt', 'ipBlocker::login');
zp_register_filter('guest_login_attempt', 'ipBlocker::login');
class ipBlocker {
function __construct() {
setOptionDefault('ipBlocker_list', serialize(array()));
setOptionDefault('ipBlocker_type', 'block');
setOptionDefault('ipBlocker_threshold', 10);
setOptionDefault('ipBlocker_timeout', 60);
}
function getOptionsSupported() {
$buttons = array(gettext('Allow') => 'allow', gettext('Block') => 'block');
$text = array_flip($buttons);
$cwd = getcwd();
chdir(SERVERPATH . '/' . UPLOAD_FOLDER);
$list = safe_glob('*.txt');
chdir($cwd);
$files = array('' => '');
foreach ($list as $file) {
$files[$file] = $file;
}
$options = array(gettext('IP list') => array('key' => 'ipBlocker_IP', 'type' => OPTION_TYPE_CUSTOM,
'order' => 4,
'desc' => sprintf(gettext('List of IP ranges to %s.'), $text[getOption('ipBlocker_type')])),
gettext('Import list') => array('key' => 'ipBlocker_import', 'type' => OPTION_TYPE_SELECTOR,
'order' => 5,
'selections' => $files,
'nullselection' => '',
'disabled' => !extensionEnabled('ipBlocker'),
'desc' => sprintf(gettext('Import an external IP list. <p class="notebox"><strong>NOTE:</strong> If this list is large it may exceed the capacity of Zenphoto and %s to process and store the results.'), DATABASE_SOFTWARE)),
gettext('Action') => array('key' => 'ipBlocker_type', 'type' => OPTION_TYPE_RADIO,
'order' => 3,
'buttons' => $buttons,
'desc' => gettext('How the plugin will interpret the IP list.')),
gettext('Logon threshold') => array('key' => 'ipBlocker_threshold', 'type' => OPTION_TYPE_TEXTBOX,
'order' => 1,
'desc' => gettext('Admin page requests will be ignored after this many failed tries.')),
gettext('Logon cool off') => array('key' => 'ipBlocker_timeout', 'type' => OPTION_TYPE_TEXTBOX,
'order' => 2,
'desc' => gettext('The block will be removed after this many minutes.'))
);
if (!extensionEnabled('ipBlocker')) {
$options['note'] = array('key' => 'ipBlocker_note', 'type' => OPTION_TYPE_NOTE,
'order' => 0,
'desc' => '<p class="notebox">' . gettext('IP list ranges cannot be managed with the plugin disabled') . '</p>');
}
return $options;
}
function handleOption($option, $currentValue) {
$list = getSerializedArray(getOption('ipBlocker_list'));
if (extensionEnabled('ipBlocker')) {
$disabled = '';
} else {
$disabled = ' disabled="disabled"';
}
switch ($option) {
case 'ipBlocker_IP':
$key = 0;
foreach ($list as $key => $range) {
?>
<input id="ipholder_<?php echo $key; ?>a" type="textbox" size="20" name="ipBlocker_ip_start_<?php echo $key; ?>"
value="<?php echo html_encode($range['start']); ?>" <?php echo $disabled; ?> />
-
<input id="ipholder_<?php echo $key; ?>b" type="textbox" size="20" name="ipBlocker_ip_end_<?php echo $key; ?>"
value="<?php echo html_encode($range['end']); ?>" <?php echo $disabled; ?> />
<br />
<?php
}
$i = $key;
while ($i < $key + 4) {
$i++;
?>
<input id="ipholder_<?php echo $i; ?>a" type="textbox" size="20" name="ipBlocker_ip_start_<?php echo $i; ?>"
value="" <?php echo $disabled; ?> />
-
<input id="ipholder_<?php echo $i; ?>b" type="textbox" size="20" name="ipBlocker_ip_end_<?php echo $i; ?>"
value="" <?php echo $disabled; ?> />
<br />
<?php
}
?>
<script type="text/javascript">
<!--
function clearips() {
<?php
for ($i = 0; $i <= $key + 4; $i++) {
?>
$('#ipholder_<?php echo $i; ?>a').val('');
$('#ipholder_<?php echo $i; ?>b').val('');
<?php
}
?>
}
</script>
<p class="buttons">
<a href="javascript:clearips();"><?php echo gettext('clear list'); ?></a>
</p>
<?php
break;
}
}
function handleOptionSave($themename, $themealbum) {
$notify = '';
$list = array();
foreach ($_POST as $key => $param) {
if ($param) {
if (strpos($key, 'ipBlocker_ip_') !== false) {
if (preg_match("/^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/", $param)) {
$p = explode('_', substr($key, 13));
$list[$p[1]][$p[0]] = $param;
}
}
}
}
foreach ($list as $key => $range) {
if (!array_key_exists('start', $range) || !array_key_exists('end', $range)) {
unset($list[$key]);
$notify .= gettext('IP address format error') . '<br />';
}
}
setOption('ipBlocker_list', serialize($list));
purgeOption('ipBlocker_import');
if (!empty($_POST['ipBlocker_import'])) {
$file = SERVERPATH . '/' . UPLOAD_FOLDER . '/' . sanitize_path($_POST['ipBlocker_import']);
if (file_exists($file)) {
$import_list = array();
foreach ($list as $range) {
$ipa = explode('.', $range['end']);
$ipend = sprintf('%03u.%03u.%03u.%03u', @$ipa[0], @$ipa[1], @$ipa[2], @$ipa[3]);
$ipa = explode('.', $range['start']);
do {
$current = sprintf('%03u.%03u.%03u.%03u', @$ipa[0], @$ipa[1], @$ipa[2], @$ipa[3]);
$ipa[3] ++;
if ($ipa[3] > 255) {
$ipa[3] = 0;
$ipa[2] ++;
if ($ipa[2] > 255) {
$ipa[2] = 0;
$ipa[2] ++;
if ($ipa[1] > 255) {
$ipa[1] = 0;
$ipa[0] ++;
if ($ipa[0] > 255) {
break;
}
}
}
}
$import_list[] = $current;
} while ($current < $ipend);
}
$import = explode("\n", file_get_contents($file));
foreach ($import as $ip) {
$ip = trim($ip);
if ($ip) {
$ipa = explode('.', $ip);
$import_list[] = sprintf('%03u.%03u.%03u.%03u', @$ipa[0], @$ipa[1], @$ipa[2], @$ipa[3]);
}
}
$list = array();
if (!empty($import_list)) {
$import_list = array_unique($import_list);
sort($import_list);
$current = $start = array_shift($import_list);
$end = $start;
$clean = false;
while (!empty($import_list)) {
$try = trim(array_shift($import_list));
if ($try) {
$ipa = explode('.', $current);
$ipa[3] ++;
if ($ipa[3] > 255) {
$ipa[3] = 0;
$ipa[2] ++;
if ($ipa[2] > 255) {
$ipa[2] = 0;
$ipa[2] ++;
if ($ipa[1] > 255) {
$ipa[1] = 0;
$ipa[0] ++;
if ($ipa[0] > 255) {
break;
}
}
}
}
$next = sprintf('%03u.%03u.%03u.%03u', @$ipa[0], @$ipa[1], @$ipa[2], @$ipa[3]);
$current = $try;
if ($clean = $current != $next) {
$list[] = array('start' => $start, 'end' => $end);
$start = $end = $current;
} else {
$end = $next;
}
}
}
if (!$clean) {
$list[] = array('start' => $start, 'end' => $end);
}
setOption('ipBlocker_list', serialize($list));
}
}
}
if ($notify)
return '&custom=' . $notify;
else
return false;
}
static function login($loggedin, $user, $pass = NULL) {
if (!$loggedin) {
self::adminGate('', '');
}
return $loggedin;
}
static function suspended() {
if ($block = getOption('ipBlocker_forbidden')) {
$block = getSerializedArray($block);
if (array_key_exists($ip = getUserIP(), $block)) {
if ($block[$ip] < (time() - getOption('ipBlocker_timeout') * 60)) {
unset($block[$ip]);
if (count($block) > 0) {
setOption('ipBlocker_forbidden', serialize($block));
} else {
setOption('ipBlocker_forbidden', NULL);
}
} else {
return true;
}
}
}
return false;
}
static function adminGate($allow, $page) {
$sql = 'DELETE FROM ' . prefix('plugin_storage') . ' WHERE `type`="ipBlocker" AND `aux` < "' . (time() - getOption('ipBlocker_timeout') * 60) . '"';
query($sql);
$sql = 'INSERT INTO ' . prefix('plugin_storage') . ' (`type`, `aux`,`data`) VALUES ("ipBlocker", "' . time() . '","' . getUserIP() . '")';
query($sql);
$count = db_count('plugin_storage', 'WHERE `type`="ipBlocker" AND `data`="' . getUserIP() . '"');
if ($count >= getOption('ipBlocker_threshold')) {
$block = getOption('ipBlocker_forbidden');
if ($block) {
$block = getSerializedArray($block);
} else {
$block = array();
}
$block[getUserIP()] = time();
setOption('ipBlocker_forbidden', serialize($block));
}
return $allow;
}
static function load($path) {
$list = getSerializedArray(getOption('ipBlocker_list'));
$allow = getOption('ipBlocker_type') == 'allow';
$gate = $allow;
if (!empty($list)) {
$ipa = explode('.', getUserIP());
$ip = sprintf('%03u.%03u.%03u.%03u', @$ipa[0], @$ipa[1], @$ipa[2], @$ipa[3]);
foreach ($list as $range) {
if ($ip >= $range['start'] && $ip <= $range['end']) {
$gate = !$allow;
break;
}
}
}
if ($gate) {
header("HTTP/1.0 403 " . gettext("Forbidden"));
header("Status: 403 " . gettext("Forbidden"));
exitZP();
} else {
return $path;
}
}
}
if (extensionEnabled('ibBlocker') && ipBlocker::suspended()) {
header("HTTP/1.0 403 " . gettext("Forbidden"));
header("Status: 403 " . gettext("Forbidden"));
exitZP();
}
?>