/* I18N: An access rule - allow access to the site */ WT_I18N::translate('allow'), 'deny' => /* I18N: An access rule - deny access to the site */ WT_I18N::translate('deny'), 'robot' => /* I18N: http://en.wikipedia.org/wiki/Web_crawler */ WT_I18N::translate('robot'), ); $controller = new WT_Controller_Page; $controller ->restrictAccess(Auth::isAdmin()) ->addExternalJavascript(WT_JQUERY_DATATABLES_JS_URL) ->addExternalJavascript(WT_DATATABLES_BOOTSTRAP_JS_URL) ->setPageTitle(WT_I18N::translate('Site access rules')); $action = WT_Filter::get('action'); switch ($action) { case 'delete': $user_access_rule_id = WT_Filter::getInteger('site_access_rule_id'); WT_DB::prepare("DELETE FROM `##site_access_rule` WHERE site_access_rule_id=?")->execute(array($user_access_rule_id)); break; case 'allow': case 'deny': case 'robot': $user_access_rule_id = WT_Filter::getInteger('site_access_rule_id'); WT_DB::prepare("UPDATE `##site_access_rule` SET rule=? WHERE site_access_rule_id=?")->execute(array($action, $user_access_rule_id)); break; case 'load_rules': Zend_Session::writeClose(); // AJAX callback for datatables $search = WT_Filter::get('search'); $search = $search['value']; $start = WT_Filter::getInteger('start'); $length = WT_Filter::getInteger('length'); $sql = "SELECT SQL_CACHE SQL_CALC_FOUND_ROWS" . " INET_NTOA(ip_address_start), ip_address_start, INET_NTOA(ip_address_end), ip_address_end, user_agent_pattern, rule, comment, site_access_rule_id" . " FROM `##site_access_rule`" . " WHERE rule<>'unknown'"; $args = array(); if ($search) { $sql .= " AND (INET_ATON(?) BETWEEN ip_address_start AND ip_address_end" . " OR INET_NTOA(ip_address_start) LIKE CONCAT('%', ?, '%')" . " OR INET_NTOA(ip_address_end) LIKE CONCAT('%', ?, '%')" . " OR user_agent_pattern LIKE CONCAT('%', ?, '%')" . " OR comment LIKE CONCAT('%', ?, '%'))"; $args[] = $search; $args[] = $search; $args[] = $search; $args[] = $search; $args[] = $search; } $order = WT_Filter::getArray('order'); if ($order) { $sql .= ' ORDER BY '; foreach ($order as $key => $value) { if ($key > 0) { $sql .= ','; } // Datatables numbers columns 0, 1, 2, ... // MySQL numbers columns 1, 2, 3, ... switch ($value['dir']) { case 'asc': $sql .= (1 + $value['column']) . ' ASC '; break; case 'desc': $sql .= (1 + $value['column']) . ' DESC '; break; } } } else { $sql .= 'ORDER BY 1 ASC'; } if ($length > 0) { $sql .= " LIMIT " . $start . ',' . $length; } // This becomes a JSON list, not a JSON array, so we need numeric keys. $data = WT_DB::prepare($sql)->execute($args)->fetchAll(PDO::FETCH_NUM); // Reformat the data for display foreach ($data as &$datum) { $site_access_rule_id = $datum[7]; $user_agent = $datum[4]; $datum[5] = $rules[$datum[5]]; $datum[7] = ''; } // Total filtered/unfiltered rows $recordsFiltered = WT_DB::prepare("SELECT FOUND_ROWS()")->fetchOne(); $recordsTotal = WT_DB::prepare("SELECT COUNT(*) FROM `##site_access_rule` WHERE rule <> 'unknown'")->fetchOne(); header('Content-type: application/json'); // See http://www.datatables.net/usage/server-side echo json_encode(array( 'draw' => WT_Filter::getInteger('draw'), // Always an integer 'recordsTotal' => $recordsTotal, 'recordsFiltered' => $recordsFiltered, 'data' => $data )); return; case 'load_unknown': Zend_Session::writeClose(); // AJAX callback for datatables $search = WT_Filter::get('search'); $search = $search['value']; $start = WT_Filter::getInteger('start'); $length = WT_Filter::getInteger('length'); $sql = "SELECT SQL_CACHE SQL_CALC_FOUND_ROWS" . " INET_NTOA(ip_address_start), ip_address_start, user_agent_pattern, DATE(updated) AS updated, site_access_rule_id" . " FROM `##site_access_rule`" . " WHERE rule='unknown'"; $args = array(); if ($search) { $sql .= " AND (INET_ATON(ip_address_start) LIKE CONCAT('%', ?, '%')" . " OR user_agent_pattern LIKE CONCAT('%', ?, '%'))"; $args[] = $search; $args[] = $search; } $order = WT_Filter::getArray('order'); if ($order) { $sql .= ' ORDER BY '; foreach ($order as $key => $value) { if ($key > 0) { $sql .= ','; } // Datatables numbers columns 0, 1, 2, ... // MySQL numbers columns 1, 2, 3, ... switch ($value['dir']) { case 'asc': $sql .= (1 + $value['column']) . ' ASC '; break; case 'desc': $sql .= (1 + $value['column']) . ' DESC '; break; } } } else { $sql .= 'ORDER BY 1 ASC'; } if ($length > 0) { $sql .= " LIMIT " . $start . ',' . $length; } // This becomes a JSON list, not a JSON array, so we need numeric keys. $data = WT_DB::prepare($sql)->execute($args)->fetchAll(PDO::FETCH_NUM); // Reformat the data for display foreach ($data as &$datum) { $site_access_rule_id = $datum[4]; $datum[4] = ''; $datum[5] = ''; $datum[6] = ''; } // Total filtered/unfiltered rows $recordsFiltered = WT_DB::prepare("SELECT FOUND_ROWS()")->fetchOne(); $recordsTotal = WT_DB::prepare("SELECT COUNT(*) FROM `##site_access_rule` WHERE rule = 'unknown'")->fetchOne(); header('Content-type: application/json'); // See http://www.datatables.net/usage/server-side echo json_encode(array( 'draw' => WT_Filter::getInteger('draw'), // Always an integer 'recordsTotal' => $recordsTotal, 'recordsFiltered' => $recordsFiltered, 'data' => $data )); return; } $controller ->pageHeader() ->addInlineJavascript(' jQuery.fn.dataTableExt.oSort["unicode-asc" ]=function(a,b) {return a.replace(/<[^<]*>/, "").localeCompare(b.replace(/<[^<]*>/, ""))}; jQuery.fn.dataTableExt.oSort["unicode-desc"]=function(a,b) {return b.replace(/<[^<]*>/, "").localeCompare(a.replace(/<[^<]*>/, ""))}; jQuery(".table-site-access-rules").dataTable({ ajax: "' . WT_SERVER_NAME . WT_SCRIPT_PATH . WT_SCRIPT_NAME . '?action=load_rules", serverSide: true, ' . WT_I18N::datatablesI18N() . ', processing: true, stateSave: true, stateDuration: 180, columns: [ /* 0 ip_address_start */ { dataSort: 1, class: "ip_address" }, /* 1 ip_address_start (sort) */ { type: "num", visible: false }, /* 2 ip_address_end */ { dataSort: 3, class: "ip_address" }, /* 3 ip_address_end (sort) */ { type: "num", visible: false }, /* 4 user_agent_pattern */ { class: "ua_string" }, /* 5 comment */ { }, /* 6 rule */ { }, /* 7 */ { sortable: false, class: "center" } ], }); jQuery(".table-unknown-site-visitors").dataTable({ ajax: "' . WT_SERVER_NAME . WT_SCRIPT_PATH . WT_SCRIPT_NAME . '?action=load_unknown", serverSide: true, ' . WT_I18N::datatablesI18N() . ', processing: true, stateSave: true, stateDuration: 180, columns: [ /* 0 ip_address */ { dataSort: 1, class: "ip_address" }, /* 0 ip_address (sort) */ { type: "num", visible: false }, /* 1 user_agent_pattern */ { class: "ua_string" }, /* 2 updated */ { class: "ua_string" }, /* 3 */ { sortable: false, class: "center" }, /* 4 */ { sortable: false, class: "center" }, /* 5 */ { sortable: false, class: "center" } ] }); '); // Delete any "unknown" visitors that are now "known". // This could happen every time we create/update a rule. WT_DB::exec( "DELETE unknown" . " FROM `##site_access_rule` AS unknown" . " JOIN `##site_access_rule` AS known ON (unknown.user_agent_pattern LIKE known.user_agent_pattern)" . " WHERE unknown.rule='unknown' AND known.rule<>'unknown'" . " AND unknown.ip_address_start BETWEEN known.ip_address_start AND known.ip_address_end" ); ?>

getPageTitle(); ?>

- -

-