requireAdminLogin()
->addExternalJavascript(WT_JQUERY_DATATABLES_URL)
->addExternalJavascript(WT_JQUERY_JEDITABLE_URL)
->setPageTitle(WT_I18N::translate('Site access rules'));
$action=safe_GET('action');
switch ($action) {
case 'delete':
$user_access_rule_id=safe_GET('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=safe_GET('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
$sql=
"SELECT 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();
$sSearch=safe_GET('sSearch');
if ($sSearch) {
$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[]=$sSearch;
$args[]=$sSearch;
$args[]=$sSearch;
$args[]=$sSearch;
$args[]=$sSearch;
}
$iSortingCols=safe_GET('iSortingCols');
if ($iSortingCols) {
$sql.=" ORDER BY ";
for ($i=0; $i<$iSortingCols; ++$i) {
// Datatables numbers columns 0, 1, 2, ...
// MySQL numbers columns 1, 2, 3, ...
switch (safe_GET('sSortDir_'.$i)) {
case 'asc':
$sql.=(1+(int)safe_GET('iSortCol_'.$i)).' ASC ';
break;
case 'desc':
$sql.=(1+(int)safe_GET('iSortCol_'.$i)).' DESC ';
break;
}
if ($i<$iSortingCols-1) {
$sql.=',';
}
}
} else {
$sql.=" ORDER BY updated DESC";
}
$iDisplayStart =(int)safe_GET('iDisplayStart');
$iDisplayLength=(int)safe_GET('iDisplayLength');
if ($iDisplayLength>0) {
$sql.=" LIMIT " . $iDisplayStart . ',' . $iDisplayLength;
}
// This becomes a JSON list, not a JSON array, so we need numeric keys.
$aaData=WT_DB::prepare($sql)->execute($args)->fetchAll(PDO::FETCH_NUM);
// Reformat the data for display
foreach ($aaData as &$row) {
$site_access_rule_id=$row[7];
$user_agent=$row[4];
$row[0]=edit_field_inline('site_access_rule-ip_address_start-'.$site_access_rule_id, $row[0]);
$row[2]=edit_field_inline('site_access_rule-ip_address_end-'.$site_access_rule_id, $row[2]);
$row[4]=edit_field_inline('site_access_rule-user_agent_pattern-'.$site_access_rule_id, $row[4]);
$row[5]=select_edit_control_inline('site_access_rule-rule-'.$site_access_rule_id, array(
'allow'=>/* 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'),
), null, $row[5]);
$row[6]=edit_field_inline('site_access_rule-comment-'.$site_access_rule_id, $row[6]);
$row[7]='';
}
// Total filtered rows
$iTotalDisplayRecords=WT_DB::prepare("SELECT FOUND_ROWS()")->fetchColumn();
// Total unfiltered rows
$iTotalRecords=WT_DB::prepare("SELECT COUNT(*) FROM `##site_access_rule` WHERE rule<>'unknown'")->fetchColumn();
header('Content-type: application/json');
echo json_encode(array( // See http://www.datatables.net/usage/server-side
'sEcho' =>(int)safe_GET('sEcho'),
'iTotalRecords' =>$iTotalRecords,
'iTotalDisplayRecords'=>$iTotalDisplayRecords,
'aaData' =>$aaData
));
exit;
case 'load_unknown':
Zend_Session::writeClose();
// AJAX callback for datatables
$sql=
"SELECT SQL_CALC_FOUND_ROWS".
" INET_NTOA(ip_address_start), ip_address_start, user_agent_pattern, site_access_rule_id".
" FROM `##site_access_rule`".
" WHERE rule='unknown'";
$args=array();
$sSearch=safe_GET('sSearch');
if ($sSearch) {
$sql.=
" AND (INET_ATON(ip_address_start) LIKE CONCAT('%', ?, '%')".
" OR user_agent_pattern LIKE CONCAT('%', ?, '%'))";
$args[]=$sSearch;
$args[]=$sSearch;
}
$iSortingCols=safe_GET('iSortingCols');
if ($iSortingCols) {
$sql.=" ORDER BY ";
for ($i=0; $i<$iSortingCols; ++$i) {
// Datatables numbers columns 0, 1, 2, ...
// MySQL numbers columns 1, 2, 3, ...
switch (safe_GET('sSortDir_'.$i)) {
case 'asc':
$sql.=(1+(int)safe_GET('iSortCol_'.$i)).' ASC ';
break;
case 'desc':
$sql.=(1+(int)safe_GET('iSortCol_'.$i)).' DESC ';
break;
}
if ($i<$iSortingCols-1) {
$sql.=',';
}
}
} else {
$sql.=" ORDER BY updated DESC";
}
$iDisplayStart =(int)safe_GET('iDisplayStart');
$iDisplayLength=(int)safe_GET('iDisplayLength');
if ($iDisplayLength>0) {
$sql.=" LIMIT " . $iDisplayStart . ',' . $iDisplayLength;
}
// This becomes a JSON list, not a JSON array, so we need numeric keys.
$aaData=WT_DB::prepare($sql)->execute($args)->fetchAll(PDO::FETCH_NUM);
// Reformat the data for display
foreach ($aaData as &$row) {
$site_access_rule_id=$row[3];
$row[3]='';
$row[4]='';
$row[5]='';
}
// Total filtered rows
$iTotalDisplayRecords=WT_DB::prepare("SELECT FOUND_ROWS()")->fetchColumn();
// Total unfiltered rows
$iTotalRecords=WT_DB::prepare("SELECT COUNT(*) FROM `##site_access_rule` WHERE rule='unknown'")->fetchColumn();
header('Content-type: application/json');
echo json_encode(array( // See http://www.datatables.net/usage/server-side
'sEcho' =>(int)safe_GET('sEcho'),
'iTotalRecords' =>$iTotalRecords,
'iTotalDisplayRecords'=>$iTotalDisplayRecords,
'aaData' =>$aaData
));
exit;
}
$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("#site_access_rules").dataTable({
"sDom": \'<"H"pf<"dt-clear">irl>t<"F"pl>\',
"sAjaxSource": "'.WT_SERVER_NAME.WT_SCRIPT_PATH.WT_SCRIPT_NAME.'?action=load_rules",
"bServerSide":true,
'.WT_I18N::datatablesI18N().',
"bJQueryUI": true,
"bAutoWidth":false,
"bProcessing": true,
"sPaginationType": "full_numbers",
"bStateSave": true,
"iCookieDuration": 180,
"aoColumns": [
/* 0 ip_address_start */ {"iDataSort": 1, "sClass": "ip_address"},
/* 1 ip_address_start (sort) */ {"sType": "numeric", "bVisible": false},
/* 2 ip_address_end */ {"iDataSort": 3, "sClass": "ip_address"},
/* 3 ip_address_end (sort) */ {"sType": "numeric", "bVisible": false},
/* 4 user_agent_pattern */ {"sClass": "ua_string"},
/* 5 comment */ {},
/* 6 rule */ {},
/* 7 */ {"bSortable": false, "sClass": "center"}
],
"fnDrawCallback": function() {
// Our JSON responses include Javascript as well as HTML. This does not get
// executed, So extract it, and execute it
jQuery("#site_access_rules script").each(function() {
eval(this.text);
});
}
});
jQuery("#unknown_site_visitors").dataTable({
"sDom": \'<"H"pf<"dt-clear">irl>t<"F"pl>\',
"sAjaxSource": "'.WT_SERVER_NAME.WT_SCRIPT_PATH.WT_SCRIPT_NAME.'?action=load_unknown",
"bServerSide":true,
'.WT_I18N::datatablesI18N().',
"bJQueryUI": true,
"bAutoWidth":false,
"bProcessing": true,
"bStateSave": true,
"iCookieDuration": 180,
"sPaginationType": "full_numbers",
"aoColumns": [
/* 0 ip_address */ {"iDataSort": 1, "sClass": "ip_address"},
/* 0 ip_address (sort) */ {"sType": "numeric", "bVisible": false},
/* 1 user_agent_pattern */ {"sClass": "ua_string"},
/* 2 */ {"bSortable": false, "sClass": "center"},
/* 3 */ {"bSortable": false, "sClass": "center"},
/* 4 */ {"bSortable": false, "sClass": "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"
);
?>