/*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' + '' + '
    Range
    CIDR
     
    ' + /* '
    Range
    CIDR
     
    ' +*/ '' ); 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( '
    ' + '

    Whois

    ' + '
    ' + str + '
    ' + '
    ' ).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( '' + '
    ' ).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( '' ); } }).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));