| 1: | <?php
|
| 2: |
|
| 3: | use Xmf\Request;
|
| 4: |
|
| 5: |
|
| 6: | include_once __DIR__ . '/admin_header.php';
|
| 7: | xoops_cp_header();
|
| 8: | include __DIR__ . '/mymenu.php';
|
| 9: | require_once XOOPS_ROOT_PATH . '/class/pagenav.php';
|
| 10: | require_once dirname(__DIR__) . '/class/gtickets.php';
|
| 11: |
|
| 12: |
|
| 13: | if (isset($_GET['num'])) {
|
| 14: | $_SERVER['REQUEST_URI'] = 'admin/center.php?page=center';
|
| 15: | }
|
| 16: |
|
| 17: | $myts = \MyTextSanitizer::getInstance();
|
| 18: | $db = XoopsDatabaseFactory::getDatabaseConnection();
|
| 19: |
|
| 20: |
|
| 21: | $pos = Request::getInt('pos', 0, 'GET');
|
| 22: | $num = Request::getInt('num', 20, 'GET');
|
| 23: |
|
| 24: |
|
| 25: | $log_table = $db->prefix($mydirname . '_log');
|
| 26: |
|
| 27: |
|
| 28: | require_once dirname(__DIR__) . '/class/protector.php';
|
| 29: | $db = XoopsDatabaseFactory::getDatabaseConnection();
|
| 30: | $protector = Protector::getInstance($db->conn);
|
| 31: | $conf = $protector->getConf();
|
| 32: |
|
| 33: |
|
| 34: |
|
| 35: |
|
| 36: |
|
| 37: | if (!empty($_POST['action'])) {
|
| 38: |
|
| 39: |
|
| 40: | if (!$xoopsGTicket->check(true, 'protector_admin')) {
|
| 41: | redirect_header(XOOPS_URL . '/', 3, $xoopsGTicket->getErrors());
|
| 42: | }
|
| 43: |
|
| 44: | if ($_POST['action'] === 'update_ips') {
|
| 45: | $error_msg = '';
|
| 46: |
|
| 47: | $lines = empty($_POST['bad_ips']) ? array() : explode("\n", trim($_POST['bad_ips']));
|
| 48: | $bad_ips = array();
|
| 49: | foreach ($lines as $line) {
|
| 50: | @list($bad_ip, $jailed_time) = explode('|', $line, 2);
|
| 51: | $bad_ips[trim($bad_ip)] = empty($jailed_time) ? 0x7fffffff : (int)$jailed_time;
|
| 52: | }
|
| 53: | if (!$protector->write_file_badips($bad_ips)) {
|
| 54: | $error_msg .= _AM_MSG_BADIPSCANTOPEN;
|
| 55: | }
|
| 56: |
|
| 57: | $group1_ips = empty($_POST['group1_ips']) ? array() : explode("\n", trim($_POST['group1_ips']));
|
| 58: | foreach (array_keys($group1_ips) as $i) {
|
| 59: | $group1_ips[$i] = trim($group1_ips[$i]);
|
| 60: | }
|
| 61: | $fp = @fopen($protector->get_filepath4group1ips(), 'w');
|
| 62: | if ($fp) {
|
| 63: | @flock($fp, LOCK_EX);
|
| 64: | fwrite($fp, serialize(array_unique($group1_ips)) . "\n");
|
| 65: | @flock($fp, LOCK_UN);
|
| 66: | fclose($fp);
|
| 67: | } else {
|
| 68: | $error_msg .= _AM_MSG_GROUP1IPSCANTOPEN;
|
| 69: | }
|
| 70: |
|
| 71: | $redirect_msg = $error_msg ? : _AM_MSG_IPFILESUPDATED;
|
| 72: | redirect_header('center.php?page=center', 2, $redirect_msg);
|
| 73: | exit;
|
| 74: | } elseif ($_POST['action'] === 'delete' && isset($_POST['ids']) && \is_array($_POST['ids'])) {
|
| 75: |
|
| 76: | foreach ($_POST['ids'] as $lid) {
|
| 77: | $lid = (int)$lid;
|
| 78: | $db->query("DELETE FROM $log_table WHERE lid='$lid'");
|
| 79: | }
|
| 80: | redirect_header('center.php?page=center', 2, _AM_MSG_REMOVED);
|
| 81: | exit;
|
| 82: | } elseif ($_POST['action'] === 'banbyip' && isset($_POST['ids']) && \is_array($_POST['ids'])) {
|
| 83: |
|
| 84: | foreach ($_POST['ids'] as $lid) {
|
| 85: | $lid = (int)$lid;
|
| 86: | $sql = "SELECT `ip` FROM $log_table WHERE lid='$lid'";
|
| 87: | $result = $db->query($sql);
|
| 88: |
|
| 89: | if (!$db->isResultSet($result)) {
|
| 90: | list($ip) = $db->fetchRow($result);
|
| 91: | $protector->register_bad_ips(0, $ip);
|
| 92: | }
|
| 93: |
|
| 94: | if ($db->isResultSet($result)) {
|
| 95: | $db->freeRecordSet($result);
|
| 96: | }
|
| 97: |
|
| 98: | }
|
| 99: | redirect_header('center.php?page=center', 2, _AM_MSG_BANNEDIP);
|
| 100: | exit;
|
| 101: | } elseif ($_POST['action'] === 'deleteall') {
|
| 102: |
|
| 103: | $db->query("DELETE FROM $log_table");
|
| 104: | redirect_header('center.php?page=center', 2, _AM_MSG_REMOVED);
|
| 105: | exit;
|
| 106: | } elseif ($_POST['action'] === 'compactlog') {
|
| 107: |
|
| 108: | $sql = "SELECT `lid`,`ip`,`type` FROM $log_table ORDER BY lid DESC";
|
| 109: | $result = $db->query($sql);
|
| 110: | if (!$db->isResultSet($result)) {
|
| 111: | throw new \RuntimeException(
|
| 112: | \sprintf(_DB_QUERY_ERROR, $sql) . $db->error(), E_USER_ERROR
|
| 113: | );
|
| 114: | }
|
| 115: | $buf = array();
|
| 116: | $ids = array();
|
| 117: | while (false !== (list($lid, $ip, $type) = $db->fetchRow($result))) {
|
| 118: | if (isset($buf[$ip . $type])) {
|
| 119: | $ids[] = $lid;
|
| 120: | } else {
|
| 121: | $buf[$ip . $type] = true;
|
| 122: | }
|
| 123: | }
|
| 124: | $db->query("DELETE FROM $log_table WHERE lid IN (" . implode(',', $ids) . ')');
|
| 125: | redirect_header('center.php?page=center', 2, _AM_MSG_REMOVED);
|
| 126: | exit;
|
| 127: | }
|
| 128: | }
|
| 129: |
|
| 130: |
|
| 131: |
|
| 132: |
|
| 133: |
|
| 134: |
|
| 135: | $sql = "SELECT count(lid) FROM $log_table";
|
| 136: | $result = $db->query($sql);
|
| 137: | if (!$db->isResultSet($result)) {
|
| 138: | throw new \RuntimeException(
|
| 139: | \sprintf(_DB_QUERY_ERROR, $sql) . $db->error(), E_USER_ERROR
|
| 140: | );
|
| 141: | }
|
| 142: | list($numrows) = $db->fetchRow($result);
|
| 143: |
|
| 144: | $sql = "SELECT l.lid, l.uid, l.ip, l.agent, l.type, l.description, UNIX_TIMESTAMP(l.timestamp), u.uname FROM $log_table l LEFT JOIN " . $db->prefix('users') . " u ON l.uid=u.uid ORDER BY timestamp DESC LIMIT $pos,$num";
|
| 145: | $result = $db->query($sql);
|
| 146: | if (!$db->isResultSet($result)) {
|
| 147: | throw new \RuntimeException(
|
| 148: | \sprintf(_DB_QUERY_ERROR, $sql) . $db->error(), E_USER_ERROR
|
| 149: | );
|
| 150: | }
|
| 151: |
|
| 152: |
|
| 153: | $nav = new XoopsPageNav($numrows, $num, $pos, 'pos', "page=center&num=$num");
|
| 154: | $nav_html = $nav->renderNav(10);
|
| 155: |
|
| 156: |
|
| 157: | $num_options = '';
|
| 158: | $num_array = array(20, 100, 500, 2000);
|
| 159: | foreach ($num_array as $n) {
|
| 160: | if ($n == $num) {
|
| 161: | $num_options .= "<option value='$n' selected>$n</option>\n";
|
| 162: | } else {
|
| 163: | $num_options .= "<option value='$n'>$n</option>\n";
|
| 164: | }
|
| 165: | }
|
| 166: |
|
| 167: |
|
| 168: |
|
| 169: |
|
| 170: | echo "<h3 style='text-align:left;'>" . $xoopsModule->name() . "</h3>\n";
|
| 171: | echo '<style>td.log_description {width: 60em; display: inline-block; word-wrap: break-word; white-space: pre-line;}</style>';
|
| 172: |
|
| 173: |
|
| 174: | if (!is_writable(dirname(__DIR__) . '/configs')) {
|
| 175: | printf("<p style='color:red;font-weight:bold;'>" . _AM_FMT_CONFIGSNOTWRITABLE . "</p>\n", dirname(__DIR__) . '/configs');
|
| 176: | }
|
| 177: |
|
| 178: |
|
| 179: | $bad_ips = $protector->get_bad_ips(true);
|
| 180: | uksort($bad_ips, 'protector_ip_cmp');
|
| 181: | $bad_ips4disp = '';
|
| 182: | foreach ($bad_ips as $bad_ip => $jailed_time) {
|
| 183: | $line = $jailed_time ? $bad_ip . '|' . $jailed_time : $bad_ip;
|
| 184: | $line = str_replace('|2147483647', '', $line);
|
| 185: | $bad_ips4disp .= htmlspecialchars($line, ENT_QUOTES) . "\n";
|
| 186: | }
|
| 187: |
|
| 188: |
|
| 189: | $group1_ips = $protector->get_group1_ips();
|
| 190: | usort($group1_ips, 'protector_ip_cmp');
|
| 191: | $group1_ips4disp = htmlspecialchars(implode("\n", $group1_ips), ENT_QUOTES);
|
| 192: |
|
| 193: |
|
| 194: | echo "
|
| 195: | <form name='ConfigForm' action='' method='POST'>
|
| 196: | " . $xoopsGTicket->getTicketHtml(__LINE__, 1800, 'protector_admin') . "
|
| 197: | <input type='hidden' name='action' value='update_ips' />
|
| 198: | <table width='95%' class='outer' cellpadding='4' cellspacing='1'>
|
| 199: | <tr valign='top' align='left'>
|
| 200: | <td class='head'>
|
| 201: | " . _AM_TH_BADIPS . "
|
| 202: | </td>
|
| 203: | <td class='even'>
|
| 204: | <textarea name='bad_ips' id='bad_ips' style='width:360px;height:60px;' spellcheck='false'>$bad_ips4disp</textarea>
|
| 205: | <br>
|
| 206: | " . htmlspecialchars($protector->get_filepath4badips(), ENT_QUOTES) . "
|
| 207: | </td>
|
| 208: | </tr>
|
| 209: | <tr valign='top' align='left'>
|
| 210: | <td class='head'>
|
| 211: | " . _AM_TH_GROUP1IPS . "
|
| 212: | </td>
|
| 213: | <td class='even'>
|
| 214: | <textarea name='group1_ips' id='group1_ips' style='width:360px;height:60px;' spellcheck='false'>$group1_ips4disp</textarea>
|
| 215: | <br>
|
| 216: | " . htmlspecialchars($protector->get_filepath4group1ips(), ENT_QUOTES) . "
|
| 217: | </td>
|
| 218: | </tr>
|
| 219: | <tr valign='top' align='left'>
|
| 220: | <td class='head'>
|
| 221: | </td>
|
| 222: | <td class='even'>
|
| 223: | <input type='submit' value='" . _GO . "' />
|
| 224: | </td>
|
| 225: | </tr>
|
| 226: | </table>
|
| 227: | </form>
|
| 228: | ";
|
| 229: |
|
| 230: |
|
| 231: | echo "
|
| 232: | <table width='95%' border='0' cellpadding='4' cellspacing='0'><tr><td>
|
| 233: | <form action='' method='GET' style='margin-bottom:0;'>
|
| 234: | <table width='95%' border='0' cellpadding='4' cellspacing='0'>
|
| 235: | <tr>
|
| 236: | <td align='left'>
|
| 237: | <select name='num' onchange='submit();'>$num_options</select>
|
| 238: | <input type='submit' value='" . _SUBMIT . "'>
|
| 239: | </td>
|
| 240: | <td align='right'>
|
| 241: | $nav_html
|
| 242: | </td>
|
| 243: | </tr>
|
| 244: | </table>
|
| 245: | </form>
|
| 246: | <form name='MainForm' action='' method='POST' style='margin-top:0;'>
|
| 247: | " . $xoopsGTicket->getTicketHtml(__LINE__, 1800, 'protector_admin') . "
|
| 248: | <input type='hidden' name='action' value='' />
|
| 249: | <table width='95%' class='outer' cellpadding='4' cellspacing='1'>
|
| 250: | <tr valign='middle'>
|
| 251: | <th width='5'><input type='checkbox' name='dummy' onclick=\"with(document.MainForm){for (i=0;i<length;i++) {if (elements[i].type=='checkbox') {elements[i].checked=this.checked;}}}\" /></th>
|
| 252: | <th>" . _AM_TH_DATETIME . '</th>
|
| 253: | <th>' . _AM_TH_USER . '</th>
|
| 254: | <th>' . _AM_TH_IP . '<br>' . _AM_TH_AGENT . '</th>
|
| 255: | <th>' . _AM_TH_TYPE . '</th>
|
| 256: | <th>' . _AM_TH_DESCRIPTION . '</th>
|
| 257: | </tr>
|
| 258: | ';
|
| 259: |
|
| 260: |
|
| 261: | $oddeven = 'odd';
|
| 262: | while (false !== (list($lid, $uid, $ip, $agent, $type, $description, $timestamp, $uname) = $db->fetchRow($result))) {
|
| 263: | $oddeven = ($oddeven === 'odd' ? 'even' : 'odd');
|
| 264: | $style = '';
|
| 265: |
|
| 266: | $ip = htmlspecialchars($ip, ENT_QUOTES);
|
| 267: | $type = htmlspecialchars($type, ENT_QUOTES);
|
| 268: | if ('{"' == substr($description, 0, 2) && defined('JSON_PRETTY_PRINT')) {
|
| 269: | $temp = json_decode($description);
|
| 270: | if (is_object($temp)) {
|
| 271: | $description = json_encode($temp, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE);
|
| 272: | $style = ' log_description';
|
| 273: | }
|
| 274: | }
|
| 275: | $description = htmlspecialchars($description, ENT_QUOTES);
|
| 276: | $uname = htmlspecialchars(($uid ? $uname : _GUESTS), ENT_QUOTES);
|
| 277: |
|
| 278: |
|
| 279: | if (preg_match('/Chrome\/([0-9.]+)/', $agent, $regs)) {
|
| 280: | $agent_short = 'Chrome ' . $regs[1];
|
| 281: | } elseif (preg_match('/MSIE\s+([0-9.]+)/', $agent, $regs)) {
|
| 282: | $agent_short = 'IE ' . $regs[1];
|
| 283: | } elseif (false !== stripos($agent, 'Gecko')) {
|
| 284: | $agent_short = strrchr($agent, ' ');
|
| 285: | } else {
|
| 286: | $agent_short = substr($agent, 0, strpos($agent, ' '));
|
| 287: | }
|
| 288: | $agent4disp = htmlspecialchars($agent, ENT_QUOTES);
|
| 289: | $agent_desc = $agent == $agent_short ? $agent4disp : htmlspecialchars($agent_short, ENT_QUOTES) . "<img src='../images/dotdotdot.gif' alt='$agent4disp' title='$agent4disp' />";
|
| 290: |
|
| 291: | echo "
|
| 292: | <tr>
|
| 293: | <td class='$oddeven'><input type='checkbox' name='ids[]' value='$lid' /></td>
|
| 294: | <td class='$oddeven'>" . formatTimestamp($timestamp) . "</td>
|
| 295: | <td class='$oddeven'>$uname</td>
|
| 296: | <td class='$oddeven'>$ip<br>$agent_desc</td>
|
| 297: | <td class='$oddeven'>$type</td>
|
| 298: | <td class='{$oddeven}{$style}'>$description</td>
|
| 299: | </tr>\n";
|
| 300: | }
|
| 301: |
|
| 302: |
|
| 303: | echo "
|
| 304: | <tr>
|
| 305: | <td colspan='8' align='left'>" . _AM_LABEL_REMOVE . "<input type='button' value='" . _AM_BUTTON_REMOVE . "' onclick='if (confirm(\"" . _AM_JS_REMOVECONFIRM . "\")) {document.MainForm.action.value=\"delete\"; submit();}' />
|
| 306: |   " . _AM_LABEL_BAN_BY_IP . "<input type='button' value='" . _AM_BUTTON_BAN_BY_IP . "' onclick='if (confirm(\"" . _AM_JS_BANCONFIRM . "\")) {document.MainForm.action.value=\"banbyip\"; submit();}' /></td>
|
| 307: | </tr>
|
| 308: | </table>
|
| 309: | <div align='right'>
|
| 310: | $nav_html
|
| 311: | </div>
|
| 312: | <div style='clear:both;'><br><br></div>
|
| 313: | <div align='right'>
|
| 314: | " . _AM_LABEL_COMPACTLOG . "<input type='button' value='" . _AM_BUTTON_COMPACTLOG . "' onclick='if (confirm(\"" . _AM_JS_COMPACTLOGCONFIRM . "\")) {document.MainForm.action.value=\"compactlog\"; submit();}' />
|
| 315: |
|
| 316: | " . _AM_LABEL_REMOVEALL . "<input type='button' value='" . _AM_BUTTON_REMOVEALL . "' onclick='if (confirm(\"" . _AM_JS_REMOVEALLCONFIRM . "\")) {document.MainForm.action.value=\"deleteall\"; submit();}' />
|
| 317: | </div>
|
| 318: | </form>
|
| 319: | </td></tr></table>
|
| 320: | ";
|
| 321: |
|
| 322: | xoops_cp_footer();
|
| 323: |
|
| 324: | |
| 325: | |
| 326: | |
| 327: | |
| 328: | |
| 329: | |
| 330: | |
| 331: |
|
| 332: | function protector_ip_cmp($a, $b)
|
| 333: | {
|
| 334: |
|
| 335: | if ((false === strpos($a, ':')) && false !== strpos($b, ':')) {
|
| 336: | return -1;
|
| 337: | }
|
| 338: |
|
| 339: | if ((false === strpos($a, '.')) && false !== strpos($b, '.')) {
|
| 340: | return 1;
|
| 341: | }
|
| 342: |
|
| 343: | if ((is_int(strpos($a, '.'))) && (is_int(strpos($b, '.')))) {
|
| 344: | $a = protector_normalize_ipv4($a);
|
| 345: | $b = protector_normalize_ipv4($b);
|
| 346: | }
|
| 347: | return strcasecmp($a, $b);
|
| 348: | }
|
| 349: |
|
| 350: | |
| 351: | |
| 352: | |
| 353: | |
| 354: | |
| 355: | |
| 356: |
|
| 357: | function protector_normalize_ipv4($n)
|
| 358: | {
|
| 359: | $temp = explode('.', $n);
|
| 360: | $n = '';
|
| 361: | foreach($temp as $k=>$v) {
|
| 362: | $t = '00'. $v;
|
| 363: | $n .= substr($t, -3);
|
| 364: | if ($k<3) {
|
| 365: | $n .= '.';
|
| 366: | }
|
| 367: | }
|
| 368: | return $n;
|
| 369: | }
|
| 370: | |