/*jslint white: true, plusplus: true, bitwise: true */
/*eslint no-mixed-spaces-and-tabs: ["error", "smart-tabs"]*/
/*!
* Project: WordPress IP Geo Block
* Copyright (c) 2013-2019 tokkonopapa (tokkonopapa@yahoo.com)
* This software is released under the MIT License.
*/
(function ($, window, document, undefined) {
// External variables
var skip_error = false,
timer_stack = [],
window_width = $(window).width(),
ip_geo_block = IP_GEO_BLOCK,
ip_geo_block_auth = IP_GEO_BLOCK_AUTH;
function ID(selector, id) {
var keys = {
'.': '.ip-geo-block-',
'#': '#ip-geo-block-',
'@': '#ip_geo_block_settings_',
'$': 'ip-geo-block-',
'%': 'ip_geo_block_',
'!': 'ip_geo_block_settings_'
};
return id !== undefined ? keys[selector] + id : keys.$ + selector;
}
function escapeHTML(str) {
return str.toString().replace(/[&<>"']/g, function (match) { //'"
return {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
}[match];
}).replace(/&(#\d{2,4}|\w{4,7});/g, "&$1;"); // revert html character entity
}
function stripTag(str) {
return str ? escapeHTML(str.toString().replace(/(<([^>]+)>)/ig, '')) : '';
}
function onresize(name, callback) {
var w = $(window).width();
if (w !== window_width) {
window_width = w;
if (timer_stack[name] === undefined) {
timer_stack[name] = {id: false, callback: callback};
}
$(window).off('resize').on('resize', function (/*event*/) {
if (false !== timer_stack[name].id) {
window.clearTimeout(timer_stack[name].id);
}
timer_stack[name].time = window.setTimeout(timer_stack[name].callback, 200);
return false;
});
}
}
function loading(id, flag) {
if (flag) {
$(ID('#', id)).addClass(ID('loading'));
} else {
$(ID('#', id)).removeClass(ID('loading'));
}
}
function confirm(msg, callback) {
if (window.confirm(stripTag(msg))) {
callback();
}
}
function warning(status, msg, cmd) {
window.alert(stripTag(msg || ip_geo_block.msg[11].replace('%s', cmd) + ' (' + status + ')'));
}
function notice_html5() {
warning(null, stripTag(ip_geo_block.msg[9]));
}
function redirect(page, tab) {
if (-1 !== window.location.href.indexOf(page)) {
window.location = stripTag(page) + (tab ? '&' + stripTag(tab) : '') + '&' + (ip_geo_block_auth.key ? (ip_geo_block_auth.key + '=' + ip_geo_block_auth.nonce) : '');
}
}
function ajax_post(id, request, callback, objs) {
if (id) {
loading(id, true);
}
request.action = ip_geo_block.action;
request.nonce = ip_geo_block.nonce;
$.ajax({
type: 'POST',
url: ip_geo_block.url,
data: request,
dataType: 'json'
})
.done(function (data/*, textStatus, jqXHR*/) {
if (callback) {
callback(data);
}
})
.fail(function (jqXHR /*,textStatus, errorThrown*/) {
if (!skip_error) {
warning(jqXHR.status, jqXHR.responseText, request.action);
}
})
.always(function () {
if (id) {
if ('object' === typeof objs) { // deferred object
$.when.apply($, objs).then(function () {
loading(id, false);
});
} else {
loading(id, false);
}
}
});
}
// Clear statistics, cache, logs
function ajax_clear(cmd, type) {
ajax_post(cmd, {
cmd: 'clear-' + cmd,
which: type
}, function (data) {
redirect(data.page, data.tab);
});
}
// Manipulate DB table for validation logs
function ajax_table(cmd) {
ajax_post(cmd, {
cmd: cmd
}, function (data) {
redirect(data.page, data.tab);
});
}
// Prevent event propergation
function stopPropergation(event) {
event.stopImmediatePropagation();
return false;
}
// Show/Hide description of WP-ZEP
function show_description(select) {
var data, desc = ID('.', 'desc');
select.next(desc).empty();
data = select.children('option:selected').data('desc');
if (data) {
select.next(desc).html($.parseHTML(data)); // jQuery 1.8+
}
}
// Fold the contents
function fold_elements(obj, stat) { // obj: ul object
if (stat) {
obj.removeClass('folding-disable');
} else {
obj.children(ID('.', 'hide')).hide();
obj.addClass('folding-disable');
obj.removeClass(ID('dropdown')).addClass(ID('dropup'));
}
}
// Show/Hide descendant elements
function show_descendants($this, $elem, mask) {
var prop = $this.prop('type') || '',
stat = (0 === prop.indexOf('checkbox') && $this.is(':checked')) ||
(0 === prop.indexOf('select' ) && '0' !== $this.val());
// checkbox
$this.siblings('input[name^="' + ID('%', 'settings') + '"]:checkbox').prop('disabled', !stat);
// folding the list
if ($.isArray($elem)) {
$.each($elem, function (i, elm) {
$(elm).nextAll(ID('.', 'settings-folding')).each(function (j, obj) {
fold_elements($(obj), stat && mask[i]);
});
});
} else {
$elem.nextAll(ID('.', 'settings-folding')).each(function (j, obj) {
fold_elements($(obj), stat && mask);
});
}
}
// Show / Hide Exceptions
function show_folding_ajax(elem) {
var id = ID('@', 'validation_ajax_');
fold_elements(
elem.closest('ul').next(),
$(id + '1').is(':checked') || $(id + '2').is(':checked')
);
}
// Encode/Decode to prevent blocking before post ajax
function base64_encode(str) {
return window.btoa(str);
}
function base64_decode(str) {
return window.atob(str);
}
// Equivalent for PHP's str_rot13
// @link http://phpjs.org/functions/str_rot13/
function str_rot13(str) {
return String(str).replace(/[a-z]/gi, function (s) {
return String.fromCharCode(s.charCodeAt(0) + (s.toLowerCase() < 'n' ? 13 : -13)); //'
});
}
// Wrapper for encode/decode strings
function encode_str(str) {
return base64_encode(str_rot13(str));
}
function decode_str(str) {
return str_rot13(base64_decode(str));
}
// File Reader
function readfile(file, callback) {
var reader = new window.FileReader();
reader.onload = function (event) {
if (callback) {
callback(event.target.result);
}
};
reader.onerror = function (event) {
warning('Error', event.target.error.code);
};
reader.readAsText(file);
}
// Enable / Disable at front-end target settings
function set_front_end($this) {
var checked = $this.is(':checked'),
select = $(ID('@', 'public_target_rule')),
behave = $(ID('@', 'public_behavior')),
parent = $this.closest('tr').nextAll('tr');
// Enable / Disable descendent items
parent.find('[name^="' + ID('%', 'settings') + '"]').prop('disabled', !checked);
// Enable / Disable description
parent.find(ID('.', 'desc')).css('opacity', checked ? 1.0 : 0.5);
// Show / Hide validation target
show_descendants($this, [select, behave], ['1' === select.val() ? true : false, behave.val()]);
// Render descendant element
if (checked) {
behave.change();
}
}
function is_blocked(result) {
return -1 === result.indexOf('pass');
}
/**
* jQuery deserialize plugin based on https://gist.github.com/nissuk/835256
*
* usage: $('form').deserialize({'name':'value', ...});
*/
$.fn.deserialize = function (json/*, options*/) {
return this.each(function () {
var key, name, value,
self = this,
data = {};
for (key in json) {
if(json.hasOwnProperty(key)) {
try {
name = stripTag(decodeURIComponent(key)); // URIError: malformed URI sequence
value = stripTag(decodeURIComponent(json[key]));
if (!data.hasOwnProperty(name)) { // !(name in data)
data[name] = [];
}
data[name].push(value);
} catch (e) {
}
}
}
$.each(data, function (name, val) {
key = $('[name="' + name + '"]:input', self).val(val);
if (key.attr('type') !== 'hidden') { // version
key.before('*');
}
});
});
};
function deserialize_json(json, clear) {
if (json) {
// Set fields on form
if ('string' === typeof json) {
json = JSON.parse(json);
}
// reset all checkboxes
if (clear) {
$('input[type="checkbox"]').prop('checked', false).change();
$('input[name*=providers]').prop('disabled', false).change();
}
// deserialize to the form
$(ID('#', 'import')).closest('form').deserialize(json);
// update textfield, checkbox (Exceptions, Mimetype)
$(ID('@', 'exception_admin') + ',' + ID('@', 'validation_mimetype')).change();
// update selection
$('select[name*="' + ID('%', 'settings') + '"]').change();
// folding list at Login form
$(ID('@', 'validation_login')).change();
// Public facing pages
set_front_end($(ID('@', 'validation_public')));
// Admin ajax/post
show_folding_ajax($(ID('@', 'validation_ajax_1')));
// Additional edge case (it should be optimized except IPInfoDB)
if (clear) {
/*$('input[name*=providers]').each(function(i, elm) {
elm = $(elm);
elm.prop('checked', json[elm.prop('name')] ? false : true);
});*/
clear = ID('%', 'settings[providers][IPInfoDB]');
$(ID('@', 'providers_IPInfoDB')).prop('checked', json[clear] ? true : false);
}
}
}
function inArray(val, arr) {
var i, n = arr.length;
val = val.replace('…', '');
for (i = 0; i < n; ++i) {
if (arr.hasOwnProperty(i) && 0 === arr[i].label.indexOf(val)) {
return i;
}
}
return -1;
}
// Split an array into chunks
function array_chunk(arr, size) {
var n = Math.ceil(arr.length / size),
r = [], i, j;
for(i = 0; i < n; ++i) {
j = i * size;
r.push(arr.slice(j, j + size)); // IE >= 9
}
return r;
}
// google chart
var chart = {
// Pie Chart
dataPie: [],
viewPie: [],
drawPie: function (id) {
var i, data;
if (chart.dataPie[id] === undefined) {
i = chart.dataPie[id] = new window.google.visualization.DataTable();
i.addColumn('string', 'Country');
i.addColumn('number', 'Requests');
data = $.parseJSON($('#' + id).attr('data-' + id));
chart.dataPie[id].addRows(data);
}
if (chart.viewPie[id] === undefined) {
chart.viewPie[id] = new window.google.visualization.PieChart(
document.getElementById(id)
);
}
if (chart.dataPie[id] !== undefined &&
chart.viewPie[id] !== undefined &&
0 < (i = $('#' + id).width())) {
chart.viewPie[id].draw(chart.dataPie[id], {
backgroundColor: { fill: 'transparent' },
chartArea: {
left: 0,
top: '5%',
width: '100%',
height: '90%'
},
sliceVisibilityThreshold: 0.015
});
}
},
// Line Chart
dataLine: [],
viewLine: [],
drawLine: function (id, datetype) {
var i, n, data;
if (chart.dataLine[id] === undefined) {
i = chart.dataLine[id] = new window.google.visualization.DataTable();
i.addColumn(datetype, 'Date' );
i.addColumn('number', 'comment');
i.addColumn('number', 'xmlrpc' );
i.addColumn('number', 'login' );
i.addColumn('number', 'admin' );
i.addColumn('number', 'public' );
data = $.parseJSON($('#' + id).attr('data-' + id));
n = data.length;
for (i = 0; i < n; ++i) {
data[i][0] = new Date(data[i][0] * 1000); // [sec] to [msec]
}
chart.dataLine[id].addRows(data);
}
if (chart.viewLine[id] === undefined) {
chart.viewLine[id] = new window.google.visualization.LineChart(
document.getElementById(id)
);
}
if (chart.dataLine[id] !== undefined &&
chart.viewLine[id] !== undefined &&
0 < (i = $('#' + id).width())) {
chart.viewLine[id].draw(chart.dataLine[id], {
legend: { position: 'bottom' },
backgroundColor: { fill: 'transparent' },
hAxis: { format: 'MM/dd' + ('datetime' === datetype ? ' HH:mm' : '') },
vAxis: { textPosition: (i > 320 ? 'out' : 'in') },
chartArea: {
left: (i > 320 ? '10%' : 0),
top: '5%',
width: '100%',
height: '75%'
}
});
}
},
// Stacked bar
dataStacked: [],
viewStacked: [],
drawStacked: function (id) {
var i, w, data, range, $id = $('#' + stripTag(id));
if (chart.dataStacked[id] === undefined) {
data = $.parseJSON($id.attr('data-' + id));
if (data) {
data.unshift(['site', 'comment', 'xmlrpc', 'login', 'admin', 'public', { role: 'link' } ]);
chart.dataStacked[id] = window.google.visualization.arrayToDataTable(data);
}
}
if (chart.viewStacked[id] === undefined) {
chart.viewStacked[id] = new window.google.visualization.BarChart(
document.getElementById(id)
);
// process for after animation
window.google.visualization.events.addListener(chart.viewStacked[id], 'animationfinish', function (/*event*/) {
// Make an array of the title in each row.
var i, a, p,
info = [],
data = chart.dataStacked[id],
n = data.getNumberOfRows(),
mode = $(ID('#', 'open-new')).prop('checked');
for (i = 0; i < n; i++) {
info.push({
label: /*escapeHTML(*/data.getValue(i, 0)/*)*/,
link: /*escapeHTML(*/data.getValue(i, 6)/*)*/
});
}
// https://stackoverflow.com/questions/12701772/insert-links-into-google-charts-api-data
n = 'http://www.w3.org/1999/xlink';
$id.find('text').each(function (i, elm) {
p = elm.parentNode;
if ('g' === p.tagName.toLowerCase() && -1 !== (i = inArray(elm.textContent, info))) {
a = document.createElementNS('http://www.w3.org/2000/svg', 'a');
a.setAttributeNS(n, 'xlink:href', info[i].link);
a.setAttributeNS(n, 'title', info[i].label);
a.setAttribute('target', mode ? '_blank' : '_self');
a.setAttribute('class', 'site');
a.appendChild(p.removeChild(elm));
p.appendChild(a);
info.splice(i, 1); // for speeding up
}
});
});
}
if (0 < (w = $id.width()) &&
chart.dataStacked[id] !== undefined &&
chart.viewStacked[id] !== undefined) {
i = ID('range');
range = $.parseJSON($('.' + i).attr('data-' + i));
data = chart.dataStacked[id];
i = 40 * data.getNumberOfRows();
chart.viewStacked[id].draw(data, {
width: w,
height: i + 80,
allowHtml: true,
isStacked: true,
legend: { position: 'top' },
chartArea: {
top: 50,
left: 90,
width: '100%',
height: i
},
hAxis: {
minValue: 0,
maxValue: range[1]
},
backgroundColor: { fill: 'transparent' },
animation: {
startup: true,
duration: 200,
easing: 'out'
}
});
}
},
ajaxStacked: function (duration, row, col, page) {
duration = Math.max( 0, Math.min( 4, duration ) );
row = Math.max( 1, Math.min( 5, row ) ) * 5;
ajax_post(null, {
cmd: 'restore-network',
which: duration,
offset: row * col * page,
length: row
}, function (data) {
var i, j, n, id, dt;
data = array_chunk(data, row);
$(ID('.', 'network')).each(function (index, obj) {
if (data[index] !== undefined) {
id = $(obj).attr('id');
dt = chart.dataStacked[id];
n = Math.min(row, data[index].length);
for (i = 0; i < n; ++i) {
// [0]:site, [1]:comment, [2]:xmlrpc, [3]:login, [4]:admin, [5]:public, [6]:link
for (j = 1; j <= 5; j++) {
dt.setValue(i, j, data[index][i][j]);
}
}
chart.drawStacked(id);
}
});
});
}
};
// google chart
function drawChart(tabNo) {
if ('object' === typeof window.google) {
if (1 === tabNo) {
if ($(ID('#', 'chart-countries')).length) {
chart.drawPie(ID('chart-countries'));
chart.drawLine(ID('chart-daily'), 'date');
}
} else if (5 === tabNo) {
$(ID('.', 'network')).each(function (i, obj) {
// chart.drawLine($(obj).attr('id'), 'datetime');
chart.drawStacked($(obj).attr('id'));
});
}
}
}
function initChart(tabNo) {
if ('object' === typeof window.google) {
var packages = ['corechart'];
if (5 === tabNo) {
packages.push('bar');
}
window.google.charts.load('current', {
packages: packages,
callback: function () {
drawChart(tabNo);
}
});
onresize('draw-chart.' + tabNo, function () {
drawChart(tabNo);
});
}
}
// Load / Save cookie using wpCookies in wp-includes/js/utils.js
function loadCookie(tabNo) {
var i, cookie = (wpCookies !== undefined && wpCookies.getHash('ip-geo-block')) || [];
for (i in cookie) {
if(cookie.hasOwnProperty(i)) {
cookie[i] = cookie[i].replace(/[^ox\d]/ig, '').split(''); // string (ooo...) to array (n)
}
}
if (cookie[tabNo] === undefined) {
cookie[tabNo] = [];
}
return cookie;
}
// cookie[tabNo][n] = 1 charactor or 'o' if empty
function saveCookie(cookie) {
var j, n, c = [];
$.each(cookie, function(i, obj) {
c[i] = '';
if (obj !== undefined) {
n = obj.length;
if (n) {
c[i] = (obj[0] || 'o').toString();
for (j = 1; j < n; ++j) {
c[i] += (obj[j] || 'o').toString();
}
}
}
});
// setHash( name, value, expires, path, domain, secure )
if (wpCookies !== undefined) {
wpCookies.setHash(
'ip-geo-block', c, new Date(Date.now() + 2592000000),
// `/wp-admin/`, `/wp-admin/network/` or `/wp/wp-admin/`
window.location.pathname.replace(/\\/g, '/').match(/.*\//) || ip_geo_block_auth.home + ip_geo_block_auth.admin
);
}
}
// Click event handler to show/hide form-table
function toggleSection(title, tabNo, cookie) {
var index = title.closest('fieldset').data('section'),
body = title.parent().nextAll('.panel-body').toggle(), border;
// Show/Hide
title.toggleClass(ID('dropup')).toggleClass(ID('dropdown'));
border = title.hasClass(ID('dropdown'));
if (border) {
body.addClass(ID('border')).trigger(ID('show-body'));
} else {
body.removeClass(ID('border'));
}
cookie[tabNo][index] = border ? 'o' : 'x';
saveCookie(cookie);
// redraw google chart
drawChart(tabNo);
}
function manageSection(tabNo) {
var cookie = loadCookie(tabNo);
// Click event handler to show/hide form-table
$(document).on('click', 'form>h2,h3', function (/*event*/) {
toggleSection($(this), tabNo, cookie);
return false;
});
// Toggle all
$(ID('#', 'toggle-sections')).on('click', function (/*event*/) {
var $this,
title = $(ID('.', 'field')).find('h2,h3'),
m = [ID('dropdown'), ID('dropup')],
n = title.filter('.' + m[0]).length;
// update cookie
title.each(function (i) {
$this = $(this);
$this.removeClass(m.join(' ')).addClass(n ? m[1] : m[0]);
$this = $this.parent().nextAll('.panel-body').toggle(n ? false : true);
if (n) {
$this.removeClass(ID('border'));
} else {
$this.addClass(ID('border')).trigger('show-body');
}
cookie[tabNo][i] = n ? 'x' : 'o';
});
// Save cookie
saveCookie(cookie);
// redraw google chart
drawChart(tabNo);
return false;
});
return cookie;
}
// form for export / import
function add_hidden_form(cmd) {
$('body').append(
'
' +
'' +
'' +
'
'
);
}
// Icons for 'Toggle section' and 'Toggle with non logged-in user'
function add_icon(dfn, span, title, icon) {
var i, j;
i = dfn.cloneNode(false);
i.setAttribute('title', stripTag(title));
j = span.cloneNode(false);
j.setAttribute('class', 'dashicons dashicons-' + icon);
i.appendChild(j);
return i;
}
/*--------------------------------------------------
* DataTables for tab 1 (Statistics) and 4 (Logs)
*--------------------------------------------------*/
function initTable(tabNo, control, options, cookie) {
// get page length from cookie
var length = (Number(cookie[tabNo][1 === tabNo ? 3 : 2]) || 0);
length = [10, 25, 50, 100][length];
$.extend(true, $.fn.dataTable.defaults, options, {
// DOM position (t:table, l:length menu, p:pagenate)
dom: 'tlp',
// Client behavior
serverSide: false,
autoWidth: false,
processing: true,
deferRender: true,
// Language
language: {
emptyTable: ip_geo_block.i18n[1],
loadingRecords: ip_geo_block.i18n[0],
processing: ip_geo_block.i18n[0],
zeroRecords: ip_geo_block.i18n[2],
lengthMenu: '_MENU_',
paginate: {
first: '«',
last: '»',
next: '›',
previous: '‹'
}
},
// Responsive
responsive: {
details: {
type: 'column',
target: 'td:nth-child(n+2)'
}
},
columnDefs: [
{ width: '1.25em', targets: 0 },
{ orderable: false, targets: 0 },
{ searchable: false, targets: 0 },
{
targets: [0],
data: null,
defaultContent: ''
}
],
// Pagenation, Page length (initial)
pagingType: 'full_numbers', // or 'simple_numbers'
lengthMenu: [10, 25, 50, 100],
pageLength: length,
// scroller
scroller: true,
scrollY: 10000, // prevent to change column width on click
scrollCollapse: true, // fit the height of table
// draw callback
drawCallback: function (settings) {
var elm = $(ID('#', control.tableID)).find('td.dataTables_empty'),
n = 'restore-logs' === control.ajaxCMD ? 3 : 2; // 2:restore-cache
// avoid recursive call for ajax source
// 1: thead, 2: empty tbody, 3: after loading data
if (n > settings.iDraw) {
elm.html(ip_geo_block.i18n[0]);
}
else if (n === settings.iDraw) {
// 'No data available in table'
elm.html(ip_geo_block.i18n[1]);
elm = $(ID('@', 'search_filter'));
if (elm.val()) { // if a filter value exists in the text field
elm.trigger('keyup'); // then search the text
}
}
}
});
// Instantiate DataTables
var table = $(ID('#', control.tableID)).DataTable({
ajax: {
url: ip_geo_block.url,
type: 'POST',
data: {
cmd: control.ajaxCMD,
action: ip_geo_block.action,
nonce: ip_geo_block.nonce
}
},
mark: true // https://github.com/julmot/datatables.mark.js/
}),
// redraw when column size changed
redraw = function () {
table.columns.adjust().responsive.recalc().draw(false); // full-hold
};
// draw when window is resized
onresize('draw-table.' + tabNo, redraw);
// Re-calculate the widths after panel-body is shown
$(ID('#', control.sectionID)).find('.panel-body').off(ID('show-body')).on(ID('show-body'), function (/*event*/) {
redraw();
return false;
})
// Handle the event of checkbox in the title header for bulk action
.off('change').on('change', 'th>input[type="checkbox"]', function (/*event*/) {
var prop = $(this).prop('checked');
$(ID('#', control.tableID)).find('td>input[type="checkbox"]').prop('checked', prop);
return false;
});
// Select target (radio button)
$(ID('#', 'select-target')).off('change').on('change', function (/*event*/) {
var val = $(this).find('input[name="' + ID('target') + '"]:checked').val();
// search only the specified column for selecting "Target"
table.columns(control.targetColumn).search('all' !== val ? val : '').draw();
return false;
}).trigger('change');
// Bulk action
$(ID('#', 'bulk-action')).off('click').on('click', function (/*event*/) {
var cmd = $(this).prev().val(), // value of selected option
texp = /(<([^>]+)>)/ig, // regular expression to strip tag
hexp = /data-hash=[\W]([\w]+)[\W]/i, // regular expression to extract hash
data = { IP: [], AS: [] }, // IP address and AS number
hash, cell, cells = table.$('input:checked'); // checked entry in table
if (!cmd) {
return false;
} else if (!cells.length) {
warning(null, ip_geo_block.msg[10]);
return false;
}
cells.each(function (/*index*/) {
cell = table.cell(this.parentNode).data();
// hash for anonymized IP address
// ex:<span><a href="#!" data-hash="abcdef0123456789">123.456.789.***</a></span>
if ('bulk-action-remove' === cmd || 'bulk-action-ip-erase' === cmd) {
hash = cell[control.columnIP].match(hexp);
hash = hash ? ',' + hash[1] : '';
} else {
hash = '';
}
data.IP.push(cell[control.columnIP].replace(texp, '') + hash);
data.AS.push(cell[control.columnAS].replace(texp, ''));
});
if (data.IP.length) {
ajax_post('loading', {
cmd: cmd,
which: data
}, function (data) {
if (data.page !== undefined) {
redirect(data.page, 'tab=' + tabNo);
} else if (data) {
table.ajax.reload();
$(ID('#', control.tableID)).find('th input[type="checkbox"]').prop('checked', false);
}
});
}
return false;
});
// Search filter
$(ID('@', 'search_filter')).off('keyup').on('keyup', function (/*event*/) {
table.search(this.value, false, true, !/[A-Z]/.test(this.value)).draw();
return false;
});
// Reset filter
$(ID('#', 'reset-filter')).off('click').on('click', function (/*event*/) {
$(ID('@', 'search_filter')).val('');
table.search('').draw();
return false;
});
// Clear all
$(ID('@', 'clear_all')).off('click').on('click', function (/*event*/) {
confirm(ip_geo_block.msg[0], function () {
ajax_clear(tabNo === 1 ? 'cache' : 'logs', null);
});
return false;
});
// Jump to search tab with opening a new window
// @note: `click` cannot be `off` because it's a root.
$('table' + ID('.', 'dataTable') + ' tbody').on('click', 'a', function (/*event*/) {
var p = window.location.search.slice(1).split('&'),
n = p.length, q = {}, i, j;
for (i = 0; i < n; ++i) {
j = p[i].split('=');
q[j[0]] = j[1];
}
// additional query
q.tab = tabNo === 1 ? 4 : 2;
q.s = $(this).text().replace(/[^\w\.\:\*]/, '');
j = [];
for (i in q) {
if (q.hasOwnProperty(i)) {
j.push(i + '=' + q[i]);
}
}
window.open(window.location.pathname + '?' + j.join('&'), '_blank');
return false;
});
// save cookie when length menu is changed
$(ID('#', control.tableID)).on('length.dt', function (e, settings, len) {
cookie[tabNo][1 === tabNo ? 3 : 2] = ({10:0, 25:1, 50:2, 100:3}[len] || 0);
saveCookie(cookie);
});
return table;
}
$(function () {
// Get tab number
var tabNo = Number(ip_geo_block.tab) || 0,
// Attach event handler and manage cookie
cookie = manageSection(tabNo);
// Inhibit to submit by return key
$(ID('.', 'inhibit')).on('submit', function () {
return false;
});
// Prevent warning when page transition happens during ajax
$(window).on('beforeunload', function(/*event*/) {
skip_error = true;
return;
});
// Register event handler at specific tab
switch (tabNo) {
/*----------------------------------------
* Settings
*----------------------------------------*/
case 0:
// Name of base class
var name = ID('%', 'settings');
/*--------------------------------
* Validation rules and behavior
*--------------------------------*/
// Scan your country code
$('[id^="' + ID('scan-') + '"]').on('click', function (/*event*/) {
var $this = $(this),
id = $this.attr('id'),
parent = $this.parent();
ajax_post(id.replace(/^.*(?:scan)/, 'scanning'), {
cmd: 'scan-code',
which: id.replace(ID('scan-'), '')
}, function (data) {
if (!parent.children('ul').length) {
parent.append('');
}
parent = parent.children('ul').empty();
var key, val;
for (key in data) {
if (data.hasOwnProperty(key)) {
key = stripTag(key);
if ('string' === typeof data[key]) {
val = stripTag(data[key]);
} else {
val = stripTag(data[key].code);
key = '' + key + '';
}
parent.append('' + key + ' : ' + val + '');
}
}
parent.show('slow');
});
return false; //
});
// Matching rule
$(ID('@', 'matching_rule')).on('change', function () {
var value = this.value;
$(ID('@', 'white_list')).closest('tr').toggle(value === '0');
$(ID('@', 'black_list')).closest('tr').toggle(value === '1');
return false;
}).change();
// CIDR calculator
$(ID('.', 'icon-cidr')).on('click', function () {
var src = $(ID('#', 'admin-styles-css')).get(0).href,
win = window.open('about:blank', '', 'width=560,height=170'); // menubar=no,toolbar=no,location=no
src = src.slice(0, src.lastIndexOf('css/'));
win.document.write(
'' +
'' +
'' +
'CIDR calculator for IPv4 / IPv6' +
'' +
'' +
/* '' +*/
''
);
win.document.close();
return false;
});
// Show/Hide folding list at prevent malicious upload
$(ID('@', 'validation_mimetype')).on('change', function (event) {
var $this = $(this),
stat = Number($this.val());
$this.nextAll(ID('.', 'settings-folding')).each(function (i, obj) {
fold_elements($(obj), (stat === i + 1) || (stat && 2 === i));
});
return stopPropergation(event);
}).change();
// Response message and Redirect URL
$('select[name*="response_code"]').on('change', function (event) {
var $this = $(this),
res = parseInt($this.val() / 100, 10),
elm = $this.closest('tr').nextAll('tr');
// only for Front-end target settings
if (0 <= $this.attr('name').indexOf('public')) {
if (-1 === Number($(ID('@', 'public_matching_rule')).val())) {
elm.each(function (index) {
if (1 >= index) {
$(this).hide();
}
});
return stopPropergation(event);
}
}
if (res <= 3) { // 2xx, 3xx
elm.each(function (index) {
if (0 === index) { $(this).show(); } // redirect_uri
else if (1 === index) { $(this).hide(); } // response_msg
});
} else { // 4xx, 5xx
elm.each(function (index) {
if (0 === index) { $(this).hide(); } // redirect_uri
else if (1 === index) { $(this).show(); } // response_msg
});
}
return stopPropergation(event);
}).change();
// Decode
$(ID('#', 'decode')).on('click', function (/*event*/) {
var elm = $(ID('@', 'signature')),
str = elm.val();
if (str.search(/,/) === -1) {
elm.val(decode_str(str));
} else {
elm.val(encode_str(str));
}
return false;
});
/*---------------------------
* Back-end target settings
*---------------------------*/
// Show/Hide folding list at Login form
$(ID('@', 'validation_login')).on('change', function (event) {
var $this = $(this);
show_descendants($this, $this, name, true);
return stopPropergation(event);
}).change();
// Exceptions for Admin ajax/post
ajax_post(null, {
cmd: 'get-actions'
}, function (data) {
var i, j, id, key, $this = $(ID('#', 'list-admin')),
li = document.createElement('li' ),
input = document.createElement('input'),
label = document.createElement('label'),
dfn = document.createElement('dfn' ),
span = document.createElement('span' );
for (key in data) {
if (data.hasOwnProperty(key)) {
key = stripTag(key);
if (!$this.find('#' + (id = ID('!', 'exception_admin_' + key))).size()) {
i = input.cloneNode(false);
i.setAttribute('id', id);
i.setAttribute('value', key);
i.setAttribute('type', 'checkbox');
j = li.cloneNode(false);
j.appendChild(i);
i = label.cloneNode(false);
i.setAttribute('for', id);
i.appendChild(document.createTextNode(key));
j.appendChild(i);
if (1 & data[key]) {
j.appendChild(add_icon(dfn, span, ip_geo_block.msg[5], 'lock'));
}
if (2 & data[key]) {
j.appendChild(add_icon(dfn, span, ip_geo_block.msg[6], 'unlock'));
}
$this.append(j);
}
}
}
// Admin ajax/post: `Toggle non logged-in user` at `Exceptions`
$(ID('.', 'icon-unlock')).on('click', function (/*event*/) {
$(ID('#', 'list-admin') + '>li').filter(function (/*i, elm*/) {
return ! $(this).find('.dashicons-unlock').length;
}).toggle();
return false;
});
// Admin ajax/post: Handle text field for actions
$(ID('@', 'exception_admin')).on('change', function (event) {
var actions = $.grep($(this).val().split(','), function (e){
return '' !== e.replace(/^\s+|\s+$/g, ''); // remove empty element
});
$(ID('#', 'list-admin')).find('input').each(function (/*i, obj*/) {
var $this = $(this),
action = $this.val();
$this.prop('checked', -1 !== $.inArray(action, actions));
});
return stopPropergation(event);
}).change();
// Admin ajax/post: Candidate actions
$(ID('#', 'list-admin')).on('click', 'input', function (/*event*/) {
var i,
$this = $(this),
$text = $(ID('@', 'exception_admin')),
action = $this.val(),
actions = $.grep($text.val().split(','), function (e) {
return '' !== e.replace(/^\s+|\s+$/g, ''); // remove empty element
});
// find the action
i = $.inArray(action, actions);
if (-1 === i) {
actions.push(action);
} else {
actions.splice(i, 1);
}
$text.val(actions.join(',')).change();
});
// Admin ajax/post: Find the blocked request in logs
$(ID('.', 'icon-find')).on('click', function (/*event*/) {
var $this = $(this),
list = [], n = 0, key, ext, id, s,
title = stripTag(ip_geo_block.msg[8]),
target = stripTag($this.data('target')); // `admin`, `plugins`, `themes`
// show description
$(ID('#', 'find-' + target)).empty();
$this.next().children(ID('.', 'find-desc')).show();
// make list of target
$this = $(ID('#', 'list-' + target));
$this.children('li').each(function (i, obj) {
list.push($(obj).find('input').val());
});
ajax_post('find-' + target, {
cmd: 'find-' + target
}, function (data) {
var val;
for (val in data) {
if (data.hasOwnProperty(val)) {
++n;
key = stripTag(data[val]); // page, action, plugins, themes
val = stripTag(val); // slug of target
ext = $.inArray(val, list); // slug already exists
id = ID('!', 'exception_' + target + '_' + val);
// make an anchor tab with search query
s = 'admin' === target ? (key + ' ' + val) : ('/' + key + '/' + val + '/');
s = '';
// add a new list when not found in existent key
if (ext < 0) {
list.push(val);
$this.prepend(
'' : 'name=ip_geo_block_settings[exception][' + target + '][' + val + '] />')
+ ''
);
}
// append button when found in existent key
else {
id = $this.find('#' + id).parent();
if (!id.find('a').length) {
id.append(s);
}
}
}
}
// update status of checkbox
$(ID('@', 'exception_' + target)).trigger('change');
$(ID('#', 'find-' + target)).append(
' ' + '' + stripTag(ip_geo_block.msg[7].replace('%d', n)) + ''
);
});
return false;
});
});
// Admin ajax/post: Enable / Disable Exceptions
$('input[id^="' + ID('!', 'validation_ajax_') + '"]').on('change', function (/*event*/) {
show_folding_ajax($(this));
}).change();
/*---------------------------
* Front-end target settings
*---------------------------*/
// Enable / Disable for Public facing pages
$(ID('@', 'validation_public')).on('change', function (event) {
set_front_end($(this));
return stopPropergation(event);
}).change();
// Matching rule on front-end
$(ID('@', 'public_matching_rule')).on('change', function (event) {
var value = this.value;
$(ID('@', 'public_white_list' )).closest('tr').toggle(value === '0');
$(ID('@', 'public_black_list' )).closest('tr').toggle(value === '1');
$(ID('@', 'public_response_code')).change().closest('tr').toggle(value !== '-1');
return stopPropergation(event);
}).change();
// Badly-behaved bots and crawlers
$(ID('@', 'public_behavior')).on('change', function (event) {
var $this = $(this);
fold_elements($this.siblings('ul'), $this.prop('checked'));
return stopPropergation(event);
}).change();
/*---------------------------
* Local database settings
*---------------------------*/
// Update local database
$(ID('@', 'update')).on('click', function (/*event*/) {
ajax_post('download', {
cmd: 'download'
}, function (res) {
var api, key, data;
for (api in res) {
if (res.hasOwnProperty(api)) {
data = res[api];
for (key in data) { // key: ipv4, ipv6
if (data.hasOwnProperty(key)) {
key = stripTag(key);
if (data[key].filename) {
$(ID('@', api + '_' + key + '_path')).val(stripTag(data[key].filename));
}
if (data[key].message) {
$(ID('#', api + '-' + key)).text(stripTag(data[key].message));
}
}
}
}
}
});
return false;
});
/*--------------------------------
* Privacy and record settings
*--------------------------------*/
$(ID('@', 'restrict_api')).on('change', function (/*event*/) {
$('input[class*="remote"]').prop('disabled', $(this).prop('checked'));
}).trigger('change');
$(ID('@', 'save_statistics')).on('change', function (/*event*/) {
$(ID('@', 'validation_recdays')).prop('disabled', !$(this).prop('checked'));
return false;
}).trigger('change');
$(ID('@', 'validation_reclogs')).on('change', function (/*event*/) {
var $this = $(this);
$this.parent().parent().nextAll().find('input[id*="validation"]').prop('disabled', 0 === Number($this.prop('selectedIndex')));
}).trigger('change');
$(ID('@', 'cache_hold')).on('change', function (/*event*/) {
var checked = $(this).prop('checked');
$('input[name*="[cache_time]"]').prop('disabled', !checked);
$('select[id*="login_fails"]' ).prop('disabled', !checked);
}).trigger('change');
/*---------------------------
* Submission settings
*---------------------------*/
$(ID('@', 'comment_pos')).on('change', function (/*event*/) {
var $this = $(this);
$this.nextAll('input[type="text"]').prop('disabled', 0 === Number($this.prop('selectedIndex')));
}).trigger('change');
/*---------------------------
* Plugin settings
*---------------------------*/
// Export / Import settings
add_hidden_form('validate');
// Export settings
$(ID('#', 'export')).on('click', function (/*event*/) {
if (JSON === undefined) {
notice_html5();
return false;
}
var id = name, json = {};
$.each($(this).closest('form').serializeArray(), function (i, obj) {
if (-1 !== obj.name.indexOf(id)) {
json[obj.name] = obj.value;
}
});
json[id += '[signature]'] = encode_str(json[id]);
$(ID('#', 'export-data')).val(JSON.stringify(json));
$(ID('#', 'export-form')).submit();
return false;
});
// Import settings
$(ID('#', 'file-dialog')).on('change', function (event) {
if (window.FileReader === undefined) {
notice_html5();
return false;
}
var id, file = event.target.files[0];
if (file) {
readfile(file, function (data) {
data = JSON.parse(data);
id = name + '[signature]';
if (data[id] !== undefined) {
data[id] = encode_str(data[id]);
}
ajax_post('export-import', {
cmd: 'validate',
data: JSON.stringify(data)
}, function (data) {
deserialize_json(data, true);
});
});
}
return false;
});
$(ID('#', 'import')).on('click', function (/*event*/) {
$(ID('#', 'file-dialog')).click();
return false;
});
// Import pre-defined settings
$(ID('#', 'default')).on('click', function (/*event*/) {
confirm(ip_geo_block.msg[0], function () {
ajax_post('pre-defined', {
cmd: 'import-default'
}, function (data) {
deserialize_json(data, true);
});
});
return false;
});
$(ID('#', 'preferred')).on('click', function (/*event*/) {
confirm(ip_geo_block.msg[0], function () {
ajax_post('pre-defined', {
cmd: 'import-preferred'
}, function (data) {
deserialize_json(data, false);
});
});
return false;
});
// Reset data source for live log
$(ID('@', 'reset_live')).on('click', function (/*event*/) {
ajax_post('reset-live', {
cmd: 'reset-live'
});
return false;
});
// Emergency login link
$(ID('#', 'login-link')).on('click', function (/*event*/) {
var $this = $(this), type = ID('$', 'primary');
if ($this.hasClass(type)) {
ajax_post('login-loading', {
cmd: 'generate-link'
}, function (data) {
$this.text(ip_geo_block.msg[3]);
$this.removeClass(type).nextAll(ID('.', 'desc')).remove();
$('')
.appendTo($this.parent())
.append(
ip_geo_block.msg[4],
'' + data.link + ''
);
});
} else {
confirm(ip_geo_block.msg[0], function () {
ajax_post('login-loading', {
cmd: 'delete-link'
}, function (/*data*/) {
$this.text(ip_geo_block.msg[2]);
$this.addClass(type).nextAll(ID('.', 'desc')).remove();
});
});
}
return false;
});
// Manipulate DB table for validation logs
$(ID('@', 'diag_tables')).on('click', function (/*event*/) {
confirm(ip_geo_block.msg[0], function () {
ajax_table('diag-tables');
});
return false;
});
// Show WordPress installation info
$(ID('#', 'show-info')).on('click', function (/*event*/) {
$(ID('#', 'wp-info')).empty();
ajax_post('wp-info', {
cmd: 'show-info'
}, function (data) {
var key, res = [];
for (key in data) {
if (data.hasOwnProperty(key)) {
res.push('- ' + key + ' ' + data[key]);
}
}
// response should be escaped at server side
$(ID('#', 'wp-info')).html('').find('textarea').select();
return false;
});
});
/*---------------------------
* Common event handler
*---------------------------*/
// Show/Hide description (this change event hander should be at the last)
$('select[name^="' + name + '"]').on('change', function (/*event*/) {
var $this = $(this);
show_description($this);
show_descendants($this, $this, name, true);
return false;
}).change();
// Toggle checkbox
$(ID('.', 'icon-cycle')).on('click', function (/*event*/) {
var $that = $(this).nextAll('li'), actions,
text = $that.find(ID('@', 'exception_admin')),
cbox = $that.find('input:checkbox').filter(':visible'),
stat = cbox.filter(':checked').length;
cbox.prop('checked', !stat);
if (text.length) {
if (stat) {
text.val('');
} else {
actions = [];
cbox.each(function (i, obj) {
actions.push($(obj).val());
});
text.val(actions.join(','));
}
}
$(this).blur(); // unfocus anchor tag
return false;
});
// Folding list
$(ID('.', 'settings-folding>dfn')).on('click', function (/*event*/) {
var drop = ID('drop'),
$this = $(this).parent();
$this.children(ID('.', 'hide')).toggle();
$this.toggleClass(drop + 'up').toggleClass(drop + 'down');
if ($this.hasClass(drop + 'up')) {
$this.children('div').hide();
}
return false;
});
// Submit
$('#submit').on('click', function (/*event*/) {
var elm = $(ID('@', 'signature')), str = elm.val();
if (str.indexOf(',') !== -1) {
elm.val(encode_str(str));
}
return true;
});
break;
/*----------------------------------------
* Statistics
*----------------------------------------*/
case 1:
// https://developers.google.com/loader/#Dynamic
initChart(tabNo);
// Toggle sorting order
var order = 0;
$(ID('#', 'sort-slug')).on('click', function (/*event*/) {
var $ol = $(this).closest('ol'),
$li = $ol.children('li');
// toggle sorting
order = !order;
if (order) {
$li.sort(function (a, b) {
return $(a).text() > $(b).text();
});
} else {
$li.sort(function (a, b) {
return Number($(a).text().replace(/^.*\((\d+)\)$/, '$1')) <= Number($(b).text().replace(/^.*\((\d+)\)$/, '$1'));
});
}
$ol.children('li').remove();
$li.appendTo($ol);
});
// Statistics of validation
$(ID('@', 'clear_statistics')).on('click', function (/*event*/) {
confirm(ip_geo_block.msg[0], function () {
ajax_clear('statistics', null);
});
return false;
});
// Statistics in logs
$(ID('@', 'clear_logs')).on('click', function (/*event*/) {
confirm(ip_geo_block.msg[0], function () {
ajax_clear('logs', null);
});
return false;
});
// IP address in cache
initTable(tabNo, {
tableID: 'statistics-cache',
ajaxCMD: 'restore-cache',
sectionID: 'section-2',
targetColumn: 4,
columnIP: 1,
columnAS: 3
}, {
columns: [
{ title: '' }, // 0 checkbox
{ title: ip_geo_block.i18n[3] }, // 1 IP address
{ title: ip_geo_block.i18n[4] }, // 2 Country code
{ title: ip_geo_block.i18n[5] }, // 3 AS number
{ title: ip_geo_block.i18n[6] }, // 4 Host name
{ title: ip_geo_block.i18n[7] }, // 5 Target
{ title: ip_geo_block.i18n[8] }, // 6 Login fail/Call
{ title: ip_geo_block.i18n[9] } // 7 Elapsed[sec]
],
columnDefs: [
{ responsivePriority: 0, targets: 0 }, // checkbox
{ responsivePriority: 1, targets: 1 }, // IP address
{ responsivePriority: 2, targets: 2 }, // Country code
{ responsivePriority: 6, targets: 3 }, // AS number
{ responsivePriority: 7, targets: 4 }, // Host name
{ responsivePriority: 3, targets: 5 }, // Target
{ responsivePriority: 4, targets: 6 }, // Login fail/Call
{ responsivePriority: 5, targets: 7 }, // Elapsed[sec]
{ className: "all", targets: [0, 1, 2, 5] } // always visible
]
}, cookie);
// Export cache
add_hidden_form('export-cache');
// Export cache
$(ID('#', 'export-cache')).on('click', function (/*event*/) {
$(ID('#', 'export-form')).submit();
return false;
});
break;
/*----------------------------------------
* Logs
*----------------------------------------*/
case 4:
// Validation logs
var control = {
tableID: 'validation-logs',
sectionID: 'section-0',
targetColumn: 6,
columnIP: 3,
columnAS: 5
},
options = {
columns: [
{ title: '' }, // 0 checkbox
{ title: '' }, // 1 Time (raw)
{ title: ip_geo_block.i18n[10] }, // 2 Date
{ title: ip_geo_block.i18n[ 3] }, // 3 IP address
{ title: ip_geo_block.i18n[ 4] }, // 4 Country code
{ title: ip_geo_block.i18n[ 5] }, // 5 AS number
{ title: ip_geo_block.i18n[ 7] }, // 6 Target
{ title: ip_geo_block.i18n[11] }, // 7 Result
{ title: ip_geo_block.i18n[12] }, // 8 Request
{ title: ip_geo_block.i18n[13] }, // 9 User agent
{ title: ip_geo_block.i18n[14] }, // 10 HTTP headers
{ title: ip_geo_block.i18n[15] } // 11 $_POST data
],
columnDefs: [
{ responsivePriority: 11, targets: 0 }, // checkbox
{ responsivePriority: 0, targets: 1 }, // Time (raw)
{ responsivePriority: 1, targets: 2 }, // Date
{ responsivePriority: 2, targets: 3 }, // IP address
{ responsivePriority: 3, targets: 4 }, // Country code
{ responsivePriority: 6, targets: 5 }, // AS number
{ responsivePriority: 4, targets: 6 }, // Target
{ responsivePriority: 5, targets: 7 }, // Result
{ responsivePriority: 7, targets: 8 }, // Request
{ responsivePriority: 8, targets: 9 }, // User agent
{ responsivePriority: 9, targets: 10 }, // HTTP headers
{ responsivePriority: 10, targets: 11 }, // $_POST data
{ visible: false, targets: 1 }, // always hidden
{ className: "all", targets: [0, 2, 3, 4] }, // always visible
{ className: "none", targets: [8, 9, 10, 11] } // always hidden
]
},
// Timer for Live update and DataTables
timer_start = null,
timer_pause = null,
$timer_pause = $(ID('#', 'live-loading')),
table = null,
// Controler functions for Live update
clear_timer = function () {
if (timer_start) {
window.clearTimeout(timer_start);
timer_start = null;
}
if (timer_pause) {
$timer_pause.removeClass(ID('live-timer'));
window.clearTimeout(timer_pause);
timer_pause = null;
}
},
live_start = function (cmd) {
clear_timer();
ajax_post(cmd === undefined ? 'live-loading' : null, {
cmd: 'live-start'
}, function (res) {
if (res.error) {
warning(null, res.error);
}
else if (res.data.length) {
var i, n = res.data.length;
for (i = 0; i < n; i++) {
table.row.add(res.data[i]); // `raws.add()` doesn't work because it needs js literal object.
}
table.draw(false); // the current page will still be shown.
}
if (cmd === undefined) {
// keep updating
timer_start = window.setTimeout(live_start, ip_geo_block.interval * 1000);
}
});
},
live_stop = function (cmd, callback) {
live_start(false); // once read out the buffer
ajax_post(null, {
cmd: cmd || 'live-stop',
callback: callback
});
},
live_pause = function () {
live_stop('live-pause', function () {
$timer_pause.addClass(ID('live-timer'));
timer_pause = window.setTimeout(function () {
$(ID('#', 'live-log-stop')).prop('checked', true);
live_stop();
}, ip_geo_block.timeout * 1000);
});
},
// animation on update
new_class = ID(''),
add_class = function (row, data, prefix) {
if (is_blocked(data[7 /* result */])) {
$(row).addClass(new_class + prefix + 'blocked');
} else {
$(row).addClass(new_class + prefix + 'passed');
}
},
// Live update controler and mode
$cntl = $(ID('#', 'live-log')),
$mode = $(ID('#', 'live-update'));
// Remove animation class when animation finished
$(ID('#', 'validation-logs')).on('animationend', function (/*event*/) {
$(this).find('tr[class*="' + new_class + 'new' + '"]').each(function (/*index, obj*/) {
var $this = $(this);
if (-1 !== $this.prop('class').indexOf('passed')) {
$this.addClass(new_class + 'passed').removeClass(new_class + 'new-passed');
} else {
$this.addClass(new_class + 'blocked').removeClass(new_class + 'new-blocked');
}
});
return false;
});
// Control of live update
$cntl.on('change', function (/*event*/) {
switch($('input[name="' + ID('live-log') + '"]:checked').val()) {
case 'start':
live_start();
break;
case 'pause':
live_pause();
break;
case 'stop':
live_stop();
break;
}
});
// on change mode
$mode.on('change', function (/*event*/) {
var $tr = $cntl.closest('tr'),
mode = $mode.prop('checked'); // checked in `display_plugin_admin_page()`
cookie[tabNo][1] = mode ? 'o' : 'x';
saveCookie(cookie);
// Delete old DataTables
if (table) {
table.clear().destroy();
}
if (mode) {
$tr.show().next().next().next().nextAll().hide();
control.ajaxCMD = 'live-stop';
options.order = [1, 'desc']; // sort by `Time (raw)`
options.createdRow = function (row, data/*, index*/) {
add_class(row, data, 'new-');
};
} else {
$tr.hide().next().next().next().nextAll().show();
control.ajaxCMD = 'restore-logs';
options.order = [0, ''];
options.createdRow = function (row, data/*, index*/) {
add_class(row, data, '');
};
}
// Re-initialize DataTables
$(ID('#', 'live-log-stop')).trigger('click');
table = initTable(tabNo, control, options, cookie);
return false;
}).trigger('change');
// Preset filters
$(ID('#', 'logs-preset')).on('click', 'a', function (/*event*/) {
var value = $(this).data('value');
$(ID('@', 'search_filter')).val(value);
table.search(value, false, true, !/[A-Z]/.test(value)).draw();
return false;
});
// Export logs
add_hidden_form('export-logs');
// Export logs
$(ID('#', 'export-logs')).on('click', function (/*event*/) {
$(ID('#', 'export-form')).submit();
return false;
});
break;
/*----------------------------------------
* Search
*----------------------------------------*/
case 2:
// Google Maps API error
$(window).on(ID('gmap-error'), function () {
ajax_post(null, { cmd: 'gmap-error' }, function (data) {
redirect(data.page, data.tab);
});
});
// Initialize map if exists
var map = $(ID('#', 'map'));
if ('object' === typeof window.google) {
// Initialize map if exists
map.each(function () {
$(this).GmapRS();
});
} else {
map.each(function () {
$(this).empty().html(
''
);
});
}
// Set selected provider to cookie
var options = [];
$('select[id^="' + ID('!', 'service') + '"]').on('change', function (/*event*/) {
// make selected options in cookie
$(this).children('option').each(function (i, elm) {
options[$(elm).text()] = i;
cookie[tabNo][3 + i] = $(elm).prop('selected') ? 'o' : 'x';
});
// if selected options does not include the focused index, update it
if ('o' !== cookie[tabNo][3 + (Number(cookie[tabNo][2]) || 0)]) {
cookie[tabNo][2] = $(this).prop('selectedIndex');
}
saveCookie(cookie);
}).change();
// Search Geolocation
$(ID('@', 'get_location')).on('click', function (/*event*/) {
var whois = $(ID('#', 'whois' )),
apis = $(ID('#', 'apis' )),
list = $(ID('@', 'service')).val(), obj,
ip = $.trim($(ID('@', 'ip_address')).val());
if (ip && list) {
// Anonymize IP address
if ($(ID('@', 'anonymize')).prop('checked')) {
if (/[^0-9a-f\.:]/.test(ip)) {
warning(null, 'illegal format.');
return false;
} else if (ip.indexOf('.') !== -1) { // in case of IPv4
ip = ip.replace(/\.\w+$/, '.0');
} else { // in case of IPv6
ip = ip.split(':'); // 2001:db80:abcd:0012:0000:0000:0000:0000
ip = ip.splice(0, 4).join(':');
if (-1 === ip.indexOf('::')) {
ip += '::'; // mask the interface ID
}
ip = ip.replace(/:{3,}/, '::');
}
$(ID('@', 'ip_address')).val(ip);
}
whois.hide().empty();
apis.hide().empty();
// Get whois data
obj = $.whois(ip, function (data) {
var i, str = '';
for (i = 0; i < data.length; ++i) {
str +=
'' +
'| ' + data[i].name + ' | ' +
'' + data[i].value + ' | ' +
'
';
}
whois.html(
''
).fadeIn('slow');
// keep closing
if ('x' === cookie[tabNo][1]) {
$(ID('#', 'whois-title')).trigger('click');
}
});
// Show map
ajax_post('loading', {
cmd: 'search',
ip: ip,
which: list
}, function (data) {
var key, tabs = '',
c = Number(cookie[tabNo][2]) || 0;
for (key in data) {
if (data.hasOwnProperty(key)) {
tabs += '' + key + '';
}
}
apis.html(
'' + tabs + '
' +
''
).fadeIn('slow')
// change APIs tab
.on('click', 'a.nav-tab', function () {
var $this = $(this),
key, json = $(this).data('api'), info = '',
latitude = json ? stripTag(json.latitude ) : '0',
longitude = json ? stripTag(json.longitude) : '0',
zoom = json && (json.latitude || json.longitude) ? 7 : 2;
$this.parent().children('a').removeClass('nav-tab-active');
$this.addClass('nav-tab-active');
// last focused index
cookie[tabNo][2] = $this.data('index');
saveCookie(cookie);
for (key in json) {
if (json.hasOwnProperty(key)) {
key = stripTag(key);
json[key] = stripTag(json[key]);
if ('AS number' === key && 0 === json[key].indexOf('AS')) {
json[key] = json[key].replace(/^(AS\d+)/, '$1');
}
info +=
'' +
'' + key + ' : ' +
'' + json[key] + '' +
'';
}
}
if ('object' === typeof window.google) {
map.GmapRS('deleteMarkers').GmapRS('addMarker', {
latitude: latitude,
longitude: longitude,
title: ip,
content: '',
show: true,
zoom: zoom
});
} else {
map.empty().html(
''
);
$(ID('#', 'geoinfo')).html(
'' +
//'- ' +
// '' + 'IP address' + ' : ' +
// '' + stripTag(ip) + '' +
//'
' +
//'- ' +
// '' + 'show map' + ' : ' +
// '' + 'Click here' + '' +
//'
' +
info +
'
'
);
}
}).find('.nav-tab-active').trigger('click');
}, [obj]);
}
return false;
});
// Enter key in textbox
$(ID('@', 'ip_address')).on('keypress', function (event) {
if ((event.which && event.which === 13) || (event.keyCode && event.keyCode === 13)) {
$(ID('@', 'get_location')).click();
return false;
}
});
// Preset IP address
if ($(ID('@', 'ip_address')).val()) {
$(ID('@', 'get_location')).click();
}
break;
/*----------------------------------------
* Sites
*----------------------------------------*/
case 5:
// https://developers.google.com/loader/#Dynamic
initChart(tabNo);
// Duration to retrieve
// [0]:Section, [1]:Open a new window, [2]:Duration to retrieve, [3]:Row, [4]:Column
$('input[name=' + ID('duration') + ']:radio').on('click', function (/*event*/) {
var page = $('div[class*="paginate"]').find('a[class*="current"]').text();
cookie[tabNo][2] = $(this).val() || 0; // Duration to retrieve
cookie[tabNo][3] = cookie[tabNo][3] || 2; // Rows
cookie[tabNo][4] = cookie[tabNo][4] || 1; // Columns
saveCookie(cookie);
chart.ajaxStacked(cookie[tabNo][2], cookie[tabNo][3], cookie[tabNo][4], page - 1);
});
// Open a new window
$(ID('#', 'open-new')).on('change', function (/*event*/) {
var mode = $(this).prop('checked');
cookie[tabNo][1] = mode ? 'o' : 'x';
saveCookie(cookie);
$(ID('#', 'section-0 svg')).find('a').each(function (/*index, obj*/) {
this.setAttribute('target', mode ? '_blank' : '_self');
});
});
// Chart display layout
$(ID('#', 'apply-layout')).on('click', function (/*event*/) {
var $select = $(ID('#', 'select-layout'));
cookie[tabNo][3] = $select.find('select[name="rows"] option:selected').val();
cookie[tabNo][4] = $select.find('select[name="cols"] option:selected').val();
saveCookie(cookie);
});
// Correct the `current` class because of the structure of sub manu.
$('ul.wp-submenu>li.wp-first-item').removeClass('current').next().addClass('current');
break;
}
}); // document.ready()
}(jQuery, window, document));