Files sent for analysis.
",jQuery("#spbc_scan_accordion_tab_critical").after(i+c),o.click())}setTimeout(function(){a.html(e).css({background:"inherit"}).find(".column-primary .row-actions .tbl-row_action--"+n.add_action).remove(),spbcTblBulkActionsListen(),spbcTblRowActionsListen(),spbcStartShowHide()},5e3)}spbcBulkAction&&spbcBulkAction.click()}function spbcTblPaginationListen(){let n={action:"spbc_tbl-pagination"},a={callback:spbcTblPaginationCallback,notJson:!0};jQuery(".tbl-pagination--button").on("click",function(){jQuery(this).parents(".tbl-root").find(".tbl-pagination--button").attr("disabled","disabled")}),jQuery(".tbl-pagination--go").on("click",function(){var e=jQuery(this),t=e.parents(".tbl-root");n.page=e.siblings(".tbl-pagination--curr_page").val(),n.type=t.attr("type"),a.spinner=e.siblings(".tbl-preloader--small"),spbcSendAJAXRequest(n,a,t)}),jQuery(".tbl-pagination--prev").on("click",function(){var e=jQuery(this),t=e.parents(".tbl-root");n.page=e.parents(".tbl-pagination--wrapper").attr("prev_page"),n.type=t.attr("type"),a.spinner=e.siblings(".tbl-preloader--small"),spbcSendAJAXRequest(n,a,t)}),jQuery(".tbl-pagination--next").on("click",function(){var e=jQuery(this),t=e.parents(".tbl-root");n.page=e.parents(".tbl-pagination--wrapper").attr("next_page"),n.type=t.attr("type"),a.spinner=e.siblings(".tbl-preloader--small"),spbcSendAJAXRequest(n,a,t)}),jQuery(".tbl-pagination--end").on("click",function(){var e=jQuery(this),t=e.parents(".tbl-root");n.page=e.parents(".tbl-pagination--wrapper").attr("last_page"),n.type=t.attr("type"),a.spinner=e.siblings(".tbl-preloader--small"),spbcSendAJAXRequest(n,a,t)}),jQuery(".tbl-pagination--start").on("click",function(){var e=jQuery(this),t=e.parents(".tbl-root");n.page=1,n.type=t.attr("type"),a.spinner=e.siblings(".tbl-preloader--small"),spbcSendAJAXRequest(n,a,t)})}function spbcTblPaginationCallback(e,t,n,a){jQuery(a).html(e).find(".tbl-pagination--button").removeAttr("disabled"),spbcTblBulkActionsListen(),spbcTblRowActionsListen(),spbcTblPaginationListen(),spbcTblSortListen(),spbcStartShowHide()}function spbcTblSortListen(){let a={callback:spbcTblSortCallback,notJson:!0};jQuery(".tbl-column-sortable").on("click",function(e){var t,n;e.target.classList.contains("tbl-sorting_indicator")&&(n="links"==(t=(e=jQuery(this)).parents(".tbl-root")).attr("type")?jQuery("#spbc_tbl__scanner__outbound_links b").html():"",e={action:"spbc_tbl-sort",order_by:e.attr("id"),order:e.attr("sort_direction"),type:t.attr("type"),domain:n},spbcSendAJAXRequest(e,a,t))})}function spbcTblSortCallback(e,t,n,a){jQuery(a).html(e),spbcTblBulkActionsListen(),spbcTblRowActionsListen(),spbcTblPaginationListen(),spbcTblSortListen()}function spbcScannerSwitchTable(e,t){var e=jQuery(e),n=e.parents(".row-actions").attr("uid");spbcSendAJAXRequest({action:"spbc_tbl-switch",type:t,domain:n},{callback:spbcTblPaginationCallback,notJson:!0},e.parents(".tbl-root"))}function spbcShowHideRows(e,t){t=jQuery("."+t+"_block_"+e);t.hasClass("mob_table_active")?t.removeClass("mob_table_active"):t.addClass("mob_table_active")}function spbcEATUpdateIntervalStart(){setInterval(()=>{null!==document.querySelector('div[refresh_control_tab="analysis_log"]')&&(spbcEATAddSpinner(),spbcUpdateTableEAT(),spbcUpdateStatsEAT())},6e4)}function spbcEATAddSpinner(){var e,t;null===document.getElementById("analysis_log_counter_spinner")&&null!==(e=document.querySelector('h3[aria-controls="spbc_scan_accordion_tab_analysis_log"]'))&&((t=document.createElement("img")).class="spbc_preloader",t.alt=spbcSettings.spbcSpinner.altText,t.src=spbcSettings.spbcSpinner.imgSource,t.id="analysis_log_counter_spinner",t.style="display: none; height: 13px; position: relative; top: 2px; margin-left: 5px",e.append(t)),spbcEATSwitchSpinner()}function spbcEATSwitchSpinner(){var e=document.getElementById("analysis_log_counter_spinner");null!==e&&(e.style.display="none"===e.style.display?e.style.display="inline":e.style.display="none")}function spbcUpdateTableEAT(){var e={action:"spbc_settings__draw_elements",tab_name:"scanner",security:spbcSettings.ajax_nonce};spbcSendAJAXRequest(e,{callback:spbcUpdateTableCallbackEAT,notJson:!0,additional:null},null)}function spbcUpdateTableCallbackEAT(e){var t="#spbc_tbl__scanner_analysis_log";let n="",a=null;null!==(e=(new DOMParser).parseFromString(e,"text/html").querySelector(t))&&""!==e.innerHTML&&(n=e.innerHTML),null!==(a=null!==(a=document.querySelector(t))&&""===a.innerHTML?null:a)&&""!==n&&(a.innerHTML=n)}function spbcUpdateStatsEAT(){var e={action:"spbc_analysyis_files_stats__get_html",sub_action:"give_me_html",security:spbcSettings.ajax_nonce};spbcSendAJAXRequest(e,{callback:spbcUpdateStatsCallbackEAT,notJson:!0})}function spbcUpdateStatsCallbackEAT(e){var t=document.getElementById("spbc_analysis_files_stats");t&&(t.innerHTML=e),spbcEATSwitchSpinner()}jQuery(document).ready(function(){spbcTblBulkActionsListen(),spbcTblRowActionsListen(),spbcTblPaginationListen(),spbcTblSortListen(),spbcEATUpdateIntervalStart()});
//# sourceMappingURL=spbc-table.min.js.map
diff --git a/js/spbc-table.min.js.map b/js/spbc-table.min.js.map
index 6db5af70..e8510e6c 100644
--- a/js/spbc-table.min.js.map
+++ b/js/spbc-table.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"spbc-table.min.js","sources":["spbc-table.js"],"sourcesContent":["let spbcBulkAction = null;\nconst noConfirmActions = spbcGetNoConfirmActions(spbcPublic);\n\n/**\n * Reloads scanner accordion and set all the listeners\n * @param {string|null} interactControlTab ajaxResult If is set, will use this var as interactivity data.\n * @param {string|null} updateText\n */\nfunction spbcReloadAccordion(interactControlTab = null, updateText = '') {\n spbcSendAJAXRequest(\n {action: 'spbc_scanner_tab__reload_accordion'},\n {\n notJson: true,\n callback: function(result, data, params, obj) {\n jQuery(obj).accordion('destroy');\n jQuery(obj).html(result);\n jQuery(obj).accordion({\n header: 'h3',\n heightStyle: 'content',\n collapsible: true,\n active: false,\n });\n spbcTblBulkActionsListen();\n spbcTblRowActionsListen();\n spbcTblPaginationListen();\n spbcTblSortListen();\n spbcStartShowHide();\n if (interactControlTab !== null && updateText !== null) {\n interactScannerTab(interactControlTab, updateText);\n }\n },\n },\n jQuery('#spbc_scan_accordion'),\n );\n}\n\n/**\n * Open refreshed tab after scanner reload.\n * @param {string} controlTab\n * @param {string} updateText\n */\nfunction interactScannerTab(controlTab, updateText) {\n let refreshControlTabSelector;\n let headerSelector;\n let headerUpdateStatus;\n\n if (\n typeof(controlTab) !== 'string' ||\n controlTab === '' ||\n typeof(updateText) !== 'string' ||\n updateText === ''\n ) {\n return;\n }\n\n // init refresh controlled tabs\n refreshControlTabSelector = jQuery('#spbc_scan_accordion div[refresh_control_tab=\"' + controlTab + '\"]')[0];\n\n // init header to click\n headerSelector = 'h3[aria-controls=spbc_scan_accordion_tab_' + controlTab + ']';\n headerSelector = jQuery(headerSelector)[0];\n\n if (\n typeof(refreshControlTabSelector) === 'undefined' ||\n typeof(headerSelector) === 'undefined'\n ) {\n return;\n }\n\n // show updated caption\n jQuery('')\n .appendTo(headerSelector);\n headerUpdateStatus = jQuery('.spbc_accordion_header_caption__update_status');\n jQuery('')\n .appendTo(headerUpdateStatus);\n\n // do click to open tab\n headerSelector.click();\n\n // highlight header\n refreshControlTabSelector.setAttribute(\n 'class',\n 'ui-accordion-header ui-corner-top ui-state-default ui-accordion-icons ui-accordion-header-active',\n );\n\n // hide all actions on partial reload\n jQuery('.row-actions').hide();\n}\n\n/**\n * Table bulk actions\n */\nfunction spbcTblBulkActionsListen() {\n jQuery('.tbl-bulk_actions-all--apply')\n .off('click')\n .on('click', function() {\n // @ToDo perhaps spbcScanner.active is not defined anywhere.\n // check this and implement `active` status in the right place\n if ( spbcScanner.active ) {\n alert(spbcTableLocalize.scannerIsActive);\n return;\n }\n\n let self = jQuery(this);\n let allowedBulkActions = [\n 'approve',\n 'disapprove',\n 'send',\n 'check_analysis_status',\n 'approve_page',\n 'disapprove_page',\n 'cure',\n 'delete_from_analysis_log',\n 'restore',\n ];\n let action = self.siblings('select').children()[self.siblings('select').first()[0].selectedIndex].value;\n\n if ( allowedBulkActions.indexOf( action ) !== -1 ) {\n if (!noConfirmActions.any.includes(action)) {\n if (!confirm(spbcTable.warning_bulk)) {\n return;\n }\n }\n let data = {\n action: 'spbc_tbl-action--bulk',\n add_action: action,\n status: self.parents('.tbl-root').attr('type'),\n };\n\n if (action === 'cure') {\n spbcScannerCureBulk(self, true);\n return;\n }\n\n if (action === 'restore') {\n const selectedItems = self.closest('#spbc_tbl__scanner_cure_log').find('.cb-select');\n let selectedIds = [];\n\n selectedItems.each(function(index, element) {\n const elementId = jQuery(element).val();\n selectedIds.push(elementId);\n });\n data.selectedIds = selectedIds;\n }\n\n if (action === 'delete_from_analysis_log') {\n const selectedItems = self.closest('#spbc_tbl__scanner_analysis_log').find('.cb-select');\n let fileIds = [];\n\n selectedItems.each(function(index, element) {\n const elementId = jQuery(element).val();\n fileIds.push(elementId);\n });\n data.file_ids = fileIds;\n }\n\n let params = {\n button: this,\n spinner: self.children('.tbl-preloader--small'),\n callback: function(out) {\n spbcReloadAccordion();\n if ( action === 'check_analysis_status' && typeof out !== 'undefined') {\n let html = '
Analysis status updated.' +\n ' Total: ' + out.counters.total +\n ', updated: ' + out.counters.updated +\n ', skipped: ' + out.counters.skipped +\n ', failed: ' + out.counters.failed +\n ', queued: ' + out.counters.queued +\n '
';\n spbcModal.open().put( html );\n }\n if ( action === 'send' && typeof out !== 'undefined') {\n let html = '
Files have been sent: ' +\n out.files_sent_counter +\n '
';\n spbcModal.open().put(html);\n }\n },\n errorOutput: function( errorText, comment ) {\n if ( comment ) {\n errorText = errorText + '
' + comment;\n }\n spbcModal.open().putError( errorText );\n },\n timeout: 60000,\n };\n\n spbcSendAJAXRequest(data, params);\n } else {\n alert('This action is not supported for all files yet =(');\n }\n });\n\n jQuery('.tbl-bulk_actions--apply')\n .off('click')\n .on('click', function(e) {\n let self = spbcBulkAction || jQuery(this);\n spbcBulkAction = self;\n let action = self.siblings('select').children()[self.siblings('select').first()[0].selectedIndex].value;\n\n if (!spbcBulkAction && !noConfirmActions.any.includes(action) && !confirm(spbcTable.warning_bulk)) {\n return;\n }\n\n if (action === 'cure') {\n spbcScannerCureBulk(jQuery(this), false);\n return;\n }\n\n if (action === 'restore') {\n spbcScannerRestoreSelected(jQuery(this));\n return;\n }\n\n if (action === 'delete_from_analysis_log') {\n spbcScannerAnalysisLogDeleteFromLog(jQuery(this));\n return;\n }\n\n if (action === 'allow' || action === 'ban') {\n let sendAction = action === 'ban' ? 'deny' : action;\n let items = self.parents('.tbl-root').find('.cb-select:checked');\n if (items) {\n self.children('.tbl-preloader--small').show();\n items.each(function() {\n let ip = jQuery(this).parents('tr').find('.tbl-row_action--'+action).data('ip');\n spbcSecLogsFilterIp(ip, sendAction, true);\n jQuery(this).prop('checked', false);\n });\n }\n self.children('.tbl-preloader--small').hide();\n let msg = action === 'allow' ? 'Allowed' : 'Banned';\n let html = '
Success. Selected IPs have been ' +\n msg +\n '. Changes will be applied within 10 minutes.' +\n '
';\n spbcModal.open().put( html );\n setTimeout(spbcReloadAccordion, 1900);\n\n return;\n }\n\n if ( action !== '-1' && self.parents('.tbl-root').find('.cb-select').is(':checked') ) {\n self.children('.tbl-preloader--small').show();\n // eslint-disable-next-line max-len\n if (self.parents('.tbl-root').find('.cb-select:checked').first().parents('tr').find('.tbl-row_action--'+action)[0]) {\n self\n .parents('.tbl-root')\n .find('.cb-select:checked')\n .first()\n .parents('tr')\n .find('.tbl-row_action--'+action)\n .click();\n self.parents('.tbl-root').find('.cb-select:checked').first().prop('checked', false);\n } else {\n self.parents('.tbl-root').find('.cb-select:checked').first().prop('checked', false);\n self.click();\n }\n } else {\n self.children('.tbl-preloader--small').hide();\n spbcBulkAction = null;\n if ( action === 'check_analysis_status' || action === 'disapprove' ) {\n let html = '
';\n spbcModal.open().put( html );\n }\n if ( action === 'send') {\n let html = '
';\n spbcModal.open().put( html );\n }\n setTimeout(spbcReloadAccordion, 1900);\n }\n // reset spbcBulkAction if action is restricted\n if (noConfirmActions.restricted.includes(action)) {\n spbcBulkAction = null;\n }\n });\n}\n\n/**\n * Cure selected files\n * @param {obj} current\n * @param {boolean} allItems\n */\nfunction spbcScannerCureBulk(current, allItems = false) {\n let selectedIds = [];\n const selector = allItems ? '.cb-select' : '.cb-select:checked';\n const selectedItems = current.closest('#spbc_tbl__scanner_cure_log').find(selector);\n\n if (selectedItems.length === 0) {\n alert('Please, select elements.');\n return;\n }\n\n selectedItems.each(function(index, element) {\n const elementId = jQuery(element).val();\n selectedIds.push(elementId);\n });\n\n const data = {\n action: 'spbc_cure_selected',\n security: spbcSettings.ajax_nonce,\n selectedIds: selectedIds,\n };\n jQuery.ajax({\n type: 'POST',\n url: spbcSettings.ajaxurl,\n data: data,\n beforeSend: function() {\n current\n .closest('#spbc_tbl__scanner_cure_log')\n .find('.tbl-button---white_blue .tbl-preloader--in_button')\n .show();\n },\n success: function(result) {\n current\n .closest('#spbc_tbl__scanner_cure_log')\n .find('.tbl-button---white_blue .tbl-preloader--in_button')\n .hide();\n const displayData = result.data;\n // prepare output\n let divWrapper = document.createElement('div');\n let pMessage = document.createElement('p');\n let pCounters = document.createElement('p');\n let divFiles = document.createElement('div');\n const failedToCure = displayData.hasOwnProperty('failed_to_cure') ? displayData.failed_to_cure : [];\n if (failedToCure.length > 0) {\n divFiles.innerHTML = failedToCure.join('');\n }\n pMessage.innerHTML = displayData.message;\n pCounters.innerHTML += 'Cured: ' +\n (\n displayData.hasOwnProperty('cured_on_request') ?\n displayData.cured_on_request :\n 0\n );\n pCounters.innerHTML += ', already cured: ' +\n (\n displayData.hasOwnProperty('skipped') ?\n displayData.skipped :\n 0\n );\n pCounters.innerHTML += ', failed to cure: ' + failedToCure.length;\n\n divWrapper.append(pMessage);\n divWrapper.append(pCounters);\n divWrapper.append(divFiles);\n if (result.success) {\n spbcModal.open().put(divWrapper.outerHTML);\n } else {\n spbcModal.open().putError(divWrapper.outerHTML);\n }\n document.addEventListener('spbcModalClosed', function( e ) {\n spbcReloadAccordion();\n });\n },\n });\n}\n\n/**\n * Restore selected files\n * @param {obj} current\n */\nfunction spbcScannerRestoreSelected(current) {\n const selectedItems = current.closest('#spbc_tbl__scanner_cure_log').find('.cb-select:checked');\n let selectedIds = [];\n\n if (selectedItems.length === 0) {\n alert('Please, select elements.');\n }\n\n selectedItems.each(function(index, element) {\n const elementId = jQuery(element).val();\n selectedIds.push(elementId);\n });\n\n const data = {\n action: 'spbc_restore_selected',\n security: spbcSettings.ajax_nonce,\n selectedIds: selectedIds,\n };\n jQuery.ajax({\n type: 'POST',\n url: spbcSettings.ajaxurl,\n data: data,\n beforeSend: function() {\n current\n .closest('#spbc_tbl__scanner_cure_log')\n .find('.tbl-button---white_blue .tbl-preloader--in_button')\n .show();\n },\n success: function(result) {\n current\n .closest('#spbc_tbl__scanner_cure_log')\n .find('.tbl-button---white_blue .tbl-preloader--in_button')\n .hide();\n if (result.success) {\n spbcModal.open().put(result.data);\n document.addEventListener('spbcModalClosed', function( e ) {\n document.location.reload();\n });\n } else {\n spbcModal.open().putError(result.data);\n }\n },\n });\n}\n\n/**\n * Table row actions\n */\nfunction spbcTblRowActionsListen() {\n jQuery('.tbl-row_action--ajax')\n .off('click')\n .on('click', function() {\n if ( spbcScanner.active ) {\n alert(spbcTableLocalize.scannerIsActive);\n return;\n }\n let self = jQuery(this);\n let data = {\n action: 'spbc_tbl-action--row',\n add_action: self.attr('row-action'),\n id: self.parents('.row-actions').attr('uid'),\n cols: self.parents('.row-actions').attr('cols_amount'),\n page_url: self.parent().attr('uid'),\n page_id: self.parent().attr('page_id'),\n };\n let params = {\n callback: spbcTblRowActionsCallback,\n errorOutput: function(msg, comment, hideSupportLink) {\n spbcModal.open().putError( msg, hideSupportLink );\n },\n spinner: self.parent().siblings('.tbl-preloader--tiny'),\n };\n\n // @ToDo delete this timeout after ready task #10014\n if ( self.attr('row-action') === 'delete' ) {\n params.timeout = 60000;\n }\n\n let fileName = self.parent().parent()[0].firstChild.innerHTML;\n let confirmationHeader = spbcTable['warning_h_'+self.attr('row-action')] || spbcTable.warning_default;\n let confirmationText = spbcTable['warning_t_'+self.attr('row-action')] || '';\n // init row actions with no confirm required\n if ( spbcBulkAction || noConfirmActions.any.includes(data.add_action) ) {\n // do not request user confirmation if the action is excluded or if it is a bulk action\n spbcSendAJAXRequest(data, params, self.parents('tr'));\n } else {\n // do request confirmation otherwise\n const yesButtonText = self.attr('row-action') === 'quarantine' ? 'Quarantine' : 'Yes';\n const noButtonText = self.attr('row-action') === 'quarantine' ? 'Cancel' : 'No';\n spbcModal.open().confirm(confirmationHeader, confirmationText, fileName, (confirmed) => {\n if (confirmed) {\n spbcSendAJAXRequest(data, params, self.parents('tr'));\n }\n }, yesButtonText, noButtonText);\n }\n });\n}\n\n/**\n * Row actions with no confirm required.\n * @param {object} spbcPublic Global localized SPBC object\n * @return {{}}\n */\nfunction spbcGetNoConfirmActions(spbcPublic) {\n let noConfirmActionsEmpty = {\n 'any': [],\n 'restricted': [],\n 'defaults': [],\n };\n let noConfirmActions = noConfirmActionsEmpty;\n try {\n if ( typeof spbcPublic !== 'undefined' && spbcPublic.hasOwnProperty('no_confirm_row_actions')) {\n noConfirmActions = JSON.parse(spbcPublic.no_confirm_row_actions);\n }\n if (\n typeof noConfirmActions.any.includes !== 'function' ||\n typeof noConfirmActions.restricted.includes !== 'function' ||\n typeof noConfirmActions.defaults.includes !== 'function'\n ) {\n noConfirmActions = noConfirmActionsEmpty;\n }\n } catch (e) {\n noConfirmActions = noConfirmActionsEmpty;\n }\n return noConfirmActions;\n}\n\n/**\n * Callback for table row actions\n *\n * @param {obj|string} result\n * @param {obj} data\n * @param {obj} params\n * @param {obj} obj\n */\nfunction spbcTblRowActionsCallback(result, data, params, obj) {\n if (result.color) {\n obj.css({background: result.background, color: result.color});\n }\n if (result.html) {\n obj.parent().parent().parent().prepend(result.html);\n setTimeout(function() {\n obj.fadeOut(300);\n }, 1500);\n if ( ! spbcBulkAction) {\n setTimeout(spbcReloadAccordion, 1900);\n }\n }\n\n if (\n data.add_action === 'copy_file_info'\n ) {\n if (result.success === true && result.data.file_info) {\n window.\n prompt('Copy the file info below and send it to support@cleantalk.org: ', result.data.file_info);\n } else {\n let errorText = (typeof result.data.error !== 'undefined') ?\n result.data.error :\n 'Unknown copy_file_info error';\n spbcModal.open().putError( errorText );\n }\n }\n\n if (result.temp_html) {\n let tmp=obj.html();\n obj.html(result.temp_html);\n if (result.updated_template !== undefined) {\n let updatedType = result.updated_template_type;\n let template = result.updated_template;\n let rowsInTemplate = jQuery(template).find('.wp-list-table tbody tr');\n let countRowInTemplate = rowsInTemplate.length;\n let targetTab = jQuery('[aria-controls=\"spbc_scan_accordion_tab_' + updatedType + '\"]');\n\n if (targetTab.length > 0) {\n let table = jQuery('#spbc_tbl__scanner_' + updatedType);\n // Count files in header\n jQuery('.spbc_bad_type_count.' + updatedType + '_counter').text(countRowInTemplate);\n // Count rows in table\n let countExistingRows = table.find('.wp-list-table tbody tr').length;\n table.remove();\n jQuery('#spbc_scan_accordion_tab_' + updatedType).append(template);\n // Marked new rows\n jQuery(jQuery('#spbc_scan_accordion_tab_' + updatedType)\n .find('.wp-list-table tbody tr'))\n .each(function(index, element) {\n if (++index > countExistingRows) {\n jQuery(element).css('outline', '1px solid green');\n }\n });\n targetTab.click();\n } else {\n if (updatedType === 'analysis_log') {\n // eslint-disable-next-line max-len\n let tabHeaderTemplate = '';\n // eslint-disable-next-line max-len\n let tabBodyTemplate = '
Files sent for analysis.
' +\n template +\n '
';\n jQuery('#spbc_scan_accordion_tab_critical').after(tabHeaderTemplate + tabBodyTemplate);\n targetTab.click();\n }\n }\n }\n setTimeout(function() {\n obj\n .html(tmp)\n .css({background: 'inherit'})\n .find('.column-primary .row-actions .tbl-row_action--' + data.add_action)\n .remove();\n spbcTblBulkActionsListen();\n spbcTblRowActionsListen();\n spbcStartShowHide();\n }, 5000);\n }\n if (spbcBulkAction) {\n spbcBulkAction.click();\n }\n}\n\n/**\n * Table pagination actions\n */\nfunction spbcTblPaginationListen() {\n let data = {action: 'spbc_tbl-pagination'};\n let params = {callback: spbcTblPaginationCallback, notJson: true};\n jQuery('.tbl-pagination--button').on('click', function() {\n jQuery(this).parents('.tbl-root').find('.tbl-pagination--button').attr('disabled', 'disabled');\n });\n jQuery('.tbl-pagination--go').on('click', function() {\n let self = jQuery(this);\n let obj = self.parents('.tbl-root');\n data.page = self.siblings('.tbl-pagination--curr_page').val();\n data.type = obj.attr('type');\n params.spinner = self.siblings('.tbl-preloader--small');\n spbcSendAJAXRequest(data, params, obj);\n });\n jQuery('.tbl-pagination--prev').on('click', function() {\n let self = jQuery(this);\n let obj = self.parents('.tbl-root');\n data.page = self.parents('.tbl-pagination--wrapper').attr('prev_page');\n data.type = obj.attr('type');\n params.spinner = self.siblings('.tbl-preloader--small');\n spbcSendAJAXRequest(data, params, obj);\n });\n jQuery('.tbl-pagination--next').on('click', function() {\n let self = jQuery(this);\n let obj = self.parents('.tbl-root');\n data.page = self.parents('.tbl-pagination--wrapper').attr('next_page');\n data.type = obj.attr('type');\n params.spinner = self.siblings('.tbl-preloader--small');\n spbcSendAJAXRequest(data, params, obj);\n });\n jQuery('.tbl-pagination--end').on('click', function() {\n let self = jQuery(this);\n let obj = self.parents('.tbl-root');\n data.page = self.parents('.tbl-pagination--wrapper').attr('last_page');\n data.type = obj.attr('type');\n params.spinner = self.siblings('.tbl-preloader--small');\n spbcSendAJAXRequest(data, params, obj);\n });\n jQuery('.tbl-pagination--start').on('click', function() {\n let self = jQuery(this);\n let obj = self.parents('.tbl-root');\n data.page = 1;\n data.type = obj.attr('type');\n params.spinner = self.siblings('.tbl-preloader--small');\n spbcSendAJAXRequest(data, params, obj);\n });\n}\n\n/**\n * Callback for Table pagination actions\n *\n * @param {obj|string} result\n * @param {obj} data\n * @param {obj} params\n * @param {obj} obj\n */\nfunction spbcTblPaginationCallback(result, data, params, obj) {\n jQuery(obj)\n .html(result)\n .find('.tbl-pagination--button').removeAttr('disabled');\n spbcTblBulkActionsListen();\n spbcTblRowActionsListen();\n spbcTblPaginationListen();\n spbcTblSortListen();\n spbcStartShowHide();\n}\n\n/**\n * Table sort actions\n */\nfunction spbcTblSortListen() {\n let params = {callback: spbcTblSortCallback, notJson: true};\n jQuery('.tbl-column-sortable').on('click', function(e) {\n if (e.target.classList.contains('tbl-sorting_indicator')) {\n let self = jQuery(this);\n let obj = self.parents('.tbl-root');\n let domain = obj.attr('type') == 'links'? jQuery('#spbc_tbl__scanner__outbound_links b').html(): '';\n let data = {\n action: 'spbc_tbl-sort',\n order_by: self.attr('id'),\n order: self.attr('sort_direction'),\n type: obj.attr('type'),\n domain: domain,\n };\n spbcSendAJAXRequest(data, params, obj);\n }\n });\n}\n\n/**\n * Callback for Table sort actions\n *\n * @param {obj|string} result\n * @param {obj} data\n * @param {obj} params\n * @param {obj} obj\n */\nfunction spbcTblSortCallback(result, data, params, obj) {\n jQuery(obj).html(result);\n spbcTblBulkActionsListen();\n spbcTblRowActionsListen();\n spbcTblPaginationListen();\n spbcTblSortListen();\n}\n\njQuery(document).ready(function() {\n // Table. Row actions handler\n spbcTblBulkActionsListen();\n spbcTblRowActionsListen();\n spbcTblPaginationListen();\n spbcTblSortListen();\n spbcEATUpdateIntervalStart();\n});\n\n/**\n * Switching table handler\n * Using by inline php code\n *\n * @param {obj} obj\n * @param {obj} table\n *\n */\nfunction spbcScannerSwitchTable(obj, table) {/* eslint-disable-line no-unused-vars */\n let _obj = jQuery(obj);\n let domain = _obj.parents('.row-actions').attr('uid');\n let data = {action: 'spbc_tbl-switch', type: table, domain: domain};\n let params = {callback: spbcTblPaginationCallback, notJson: true};\n spbcSendAJAXRequest(data, params, _obj.parents('.tbl-root'));\n}\n\n/**\n * Open/close table rows handler\n * Using by inline php code\n *\n * @param {string} blockId\n * @param {string} columnKey\n */\nfunction spbcShowHideRows(blockId, columnKey) {/* eslint-disable-line no-unused-vars */\n let className = '.' + columnKey + '_block_' + blockId;\n let block = jQuery(className);\n if (block.hasClass('mob_table_active')) {\n block.removeClass('mob_table_active');\n } else {\n block.addClass('mob_table_active');\n }\n}\n\n/**\n * Starts an interval to update the analysis log table and stats every 6 seconds.\n */\nfunction spbcEATUpdateIntervalStart() {\n setInterval(() => {\n // Check if the analysis log tab is present\n if (document.querySelector('div[refresh_control_tab=\"analysis_log\"]') !== null) {\n // Add a spinner to the analysis log tab header\n spbcEATAddSpinner();\n // Update the analysis log table\n spbcUpdateTableEAT();\n // Update the analysis log stats\n spbcUpdateStatsEAT();\n }\n }, 60000);\n}\n\n/**\n * Adds a spinner to the analysis log tab header if it doesn't already exist.\n */\nfunction spbcEATAddSpinner() {\n if (document.getElementById('analysis_log_counter_spinner') === null) {\n const refreshTab = document.querySelector('h3[aria-controls=\"spbc_scan_accordion_tab_analysis_log\"]');\n if (refreshTab !== null) {\n const spinner = document.createElement('img');\n spinner.class = 'spbc_preloader';\n // todo Probably we need a validation function of spbcSettings object\n spinner.alt = spbcSettings.spbcSpinner.altText;\n spinner.src = spbcSettings.spbcSpinner.imgSource;\n spinner.id = 'analysis_log_counter_spinner';\n spinner.style = 'display: none; height: 13px; position: relative; top: 2px; margin-left: 5px';\n refreshTab.append(spinner);\n }\n }\n spbcEATSwitchSpinner();\n}\n\n/**\n * Toggles the display of the spinner in the analysis log tab header.\n */\nfunction spbcEATSwitchSpinner() {\n const spinner = document.getElementById('analysis_log_counter_spinner');\n if (spinner !== null) {\n spinner.style.display = spinner.style.display === 'none' ?\n spinner.style.display = 'inline' :\n spinner.style.display = 'none';\n }\n}\n\n/**\n * Sends an AJAX request to update the analysis log table.\n */\nfunction spbcUpdateTableEAT() {\n // Define the tab name for the request\n let tabName = 'scanner';\n // Data object containing parameters for the AJAX request\n let data = {\n action: 'spbc_settings__draw_elements',\n tab_name: tabName,\n security: spbcSettings.ajax_nonce,\n };\n // Params object with additional settings for the AJAX request\n let currentParams = {\n callback: spbcUpdateTableCallbackEAT,\n notJson: true,\n additional: null,\n };\n // Send the AJAX request with the data and params objects\n spbcSendAJAXRequest( data, currentParams, null );\n}\n\n/**\n * Callback function to update the analysis log table with new HTML content.\n *\n * @param {string} allTablesHTML - The HTML content of all tables.\n */\nfunction spbcUpdateTableCallbackEAT(allTablesHTML) {\n // select the same table element to search in the current code and update from received\n const analysisTableSelector = '#spbc_tbl__scanner_analysis_log';\n const parser = new DOMParser();\n const allTablesHTMLParsed = parser.parseFromString(allTablesHTML, 'text/html');\n\n let newTabElement = null;\n let newTabElementInnerHTML = '';\n let currentTabElement = null;\n\n // get new analysis table element and its HTML\n newTabElement = allTablesHTMLParsed.querySelector(analysisTableSelector);\n if (newTabElement !== null && newTabElement.innerHTML !== '') {\n newTabElementInnerHTML = newTabElement.innerHTML;\n }\n\n // get current analysis table element and its HTML\n currentTabElement = document.querySelector(analysisTableSelector);\n if (currentTabElement !== null && currentTabElement.innerHTML === '') {\n currentTabElement = null;\n }\n\n // update analysis table element if it's changed and new data presented\n if (currentTabElement !== null && newTabElementInnerHTML !== '') {\n currentTabElement.innerHTML = newTabElementInnerHTML;\n }\n}\n\n/**\n * Sends an AJAX request to update the analysis log stats.\n */\nfunction spbcUpdateStatsEAT() {\n // Data object containing parameters for the AJAX request\n let data = {\n action: 'spbc_analysyis_files_stats__get_html',\n sub_action: 'give_me_html',\n security: spbcSettings.ajax_nonce,\n };\n // Params object with additional settings for the AJAX request\n let params = {\n callback: spbcUpdateStatsCallbackEAT,\n notJson: true,\n };\n // Send the AJAX request with the data and params objects\n spbcSendAJAXRequest(data, params);\n}\n\n/**\n * Callback function to update the analysis log stats with new HTML content.\n *\n * @param {string} newStatsHtml - The new HTML content for the stats.\n */\nfunction spbcUpdateStatsCallbackEAT(newStatsHtml) {\n // Get the element that displays the analysis files stats\n let info = document.getElementById('spbc_analysis_files_stats');\n // If the element exists, update its inner HTML with the new stats\n if (info) {\n info.innerHTML = newStatsHtml;\n }\n // Toggle the display of the spinner in the analysis log tab header\n spbcEATSwitchSpinner();\n}\n"],"names":["let","spbcBulkAction","noConfirmActions","spbcGetNoConfirmActions","spbcPublic","spbcReloadAccordion","interactControlTab","updateText","spbcSendAJAXRequest","action","notJson","callback","result","data","params","obj","jQuery","accordion","html","header","heightStyle","collapsible","active","spbcTblBulkActionsListen","spbcTblRowActionsListen","spbcTblPaginationListen","spbcTblSortListen","spbcStartShowHide","interactScannerTab","controlTab","refreshControlTabSelector","headerUpdateStatus","headerSelector","appendTo","click","setAttribute","hide","off","on","spbcScanner","alert","spbcTableLocalize","scannerIsActive","self","this","siblings","children","first","selectedIndex","value","indexOf","any","includes","confirm","spbcTable","warning_bulk","add_action","status","parents","attr","spbcScannerCureBulk","selectedItems","closest","find","selectedIds","each","index","element","elementId","val","push","fileIds","file_ids","button","spinner","out","counters","total","updated","skipped","failed","queued","spbcModal","open","put","files_sent_counter","errorOutput","errorText","comment","putError","timeout","e","spbcScannerRestoreSelected","spbcScannerAnalysisLogDeleteFromLog","sendAction","items","msg","show","ip","spbcSecLogsFilterIp","prop","setTimeout","is","restricted","current","allItems","selector","length","security","spbcSettings","ajax_nonce","ajax","type","url","ajaxurl","beforeSend","success","displayData","divWrapper","document","createElement","pMessage","pCounters","divFiles","failedToCure","hasOwnProperty","failed_to_cure","innerHTML","join","message","cured_on_request","append","outerHTML","addEventListener","location","reload","id","cols","page_url","parent","page_id","spbcTblRowActionsCallback","hideSupportLink","yesButtonText","noButtonText","fileName","firstChild","confirmationHeader","warning_default","confirmationText","confirmed","noConfirmActionsEmpty","defaults","JSON","parse","no_confirm_row_actions","color","css","background","prepend","fadeOut","file_info","window","prompt","error","temp_html","tmp","undefined","updated_template","updatedType","updated_template_type","template","countRowInTemplate","targetTab","table","text","countExistingRows","remove","tabHeaderTemplate","tabBodyTemplate","after","spbcTblPaginationCallback","page","removeAttr","spbcTblSortCallback","domain","target","classList","contains","order_by","order","spbcScannerSwitchTable","_obj","spbcShowHideRows","blockId","columnKey","block","hasClass","removeClass","addClass","spbcEATUpdateIntervalStart","setInterval","querySelector","spbcEATAddSpinner","spbcUpdateTableEAT","spbcUpdateStatsEAT","refreshTab","getElementById","class","alt","spbcSpinner","altText","src","imgSource","style","spbcEATSwitchSpinner","display","tab_name","spbcUpdateTableCallbackEAT","additional","allTablesHTML","analysisTableSelector","newTabElementInnerHTML","currentTabElement","newTabElement","DOMParser","parseFromString","sub_action","spbcUpdateStatsCallbackEAT","newStatsHtml","info","ready"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"spbc-table.min.js","sources":["spbc-table.js"],"sourcesContent":["let spbcBulkAction = null;\nconst noConfirmActions = spbcGetNoConfirmActions(spbcPublic);\n\n/**\n * Reloads scanner accordion and set all the listeners\n * @param {string|null} interactControlTab ajaxResult If is set, will use this var as interactivity data.\n * @param {string|null} updateText\n */\nfunction spbcReloadAccordion(interactControlTab = null, updateText = '') {\n spbcSendAJAXRequest(\n {action: 'spbc_scanner_tab__reload_accordion'},\n {\n notJson: true,\n callback: function(result, data, params, obj) {\n jQuery(obj).accordion('destroy');\n jQuery(obj).html(result);\n jQuery(obj).accordion({\n header: 'h3',\n heightStyle: 'content',\n collapsible: true,\n active: false,\n });\n spbcTblBulkActionsListen();\n spbcTblRowActionsListen();\n spbcTblPaginationListen();\n spbcTblSortListen();\n spbcStartShowHide();\n if (interactControlTab !== null && updateText !== null) {\n interactScannerTab(interactControlTab, updateText);\n }\n },\n },\n jQuery('#spbc_scan_accordion'),\n );\n}\n\n/**\n * Open refreshed tab after scanner reload.\n * @param {string} controlTab\n * @param {string} updateText\n */\nfunction interactScannerTab(controlTab, updateText) {\n let refreshControlTabSelector;\n let headerSelector;\n let headerUpdateStatus;\n\n if (\n typeof(controlTab) !== 'string' ||\n controlTab === '' ||\n typeof(updateText) !== 'string' ||\n updateText === ''\n ) {\n return;\n }\n\n // init refresh controlled tabs\n refreshControlTabSelector = jQuery('#spbc_scan_accordion div[refresh_control_tab=\"' + controlTab + '\"]')[0];\n\n // init header to click\n headerSelector = 'h3[aria-controls=spbc_scan_accordion_tab_' + controlTab + ']';\n headerSelector = jQuery(headerSelector)[0];\n\n if (\n typeof(refreshControlTabSelector) === 'undefined' ||\n typeof(headerSelector) === 'undefined'\n ) {\n return;\n }\n\n // show updated caption\n jQuery('')\n .appendTo(headerSelector);\n headerUpdateStatus = jQuery('.spbc_accordion_header_caption__update_status');\n jQuery('')\n .appendTo(headerUpdateStatus);\n\n // do click to open tab\n headerSelector.click();\n\n // highlight header\n refreshControlTabSelector.setAttribute(\n 'class',\n 'ui-accordion-header ui-corner-top ui-state-default ui-accordion-icons ui-accordion-header-active',\n );\n\n // hide all actions on partial reload\n jQuery('.row-actions').hide();\n}\n\n/**\n * Table bulk actions\n */\nfunction spbcTblBulkActionsListen() {\n jQuery('.tbl-bulk_actions-all--apply')\n .off('click')\n .on('click', function() {\n // @ToDo perhaps spbcScanner.active is not defined anywhere.\n // check this and implement `active` status in the right place\n if ( spbcScanner.active ) {\n alert(spbcTableLocalize.scannerIsActive);\n return;\n }\n\n let self = jQuery(this);\n let allowedBulkActions = [\n 'approve',\n 'disapprove',\n 'send',\n 'check_analysis_status',\n 'approve_page',\n 'disapprove_page',\n 'cure',\n 'delete_from_analysis_log',\n 'restore',\n ];\n let action = self.siblings('select').children()[self.siblings('select').first()[0].selectedIndex].value;\n\n if ( allowedBulkActions.indexOf( action ) !== -1 ) {\n if (!noConfirmActions.any.includes(action)) {\n if (!confirm(spbcTable.warning_bulk)) {\n return;\n }\n }\n let data = {\n action: 'spbc_tbl-action--bulk',\n add_action: action,\n status: self.parents('.tbl-root').attr('type'),\n };\n\n if (action === 'cure') {\n spbcScannerCureBulk(self, true);\n return;\n }\n\n if (action === 'restore') {\n spbcScannerRestoreBulk(self, true);\n }\n\n if (action === 'delete_from_analysis_log') {\n const selectedItems = self.closest('#spbc_tbl__scanner_analysis_log').find('.cb-select');\n let fileIds = [];\n\n selectedItems.each(function(index, element) {\n const elementId = jQuery(element).val();\n fileIds.push(elementId);\n });\n data.file_ids = fileIds;\n }\n\n let params = {\n button: this,\n spinner: self.children('.tbl-preloader--small'),\n callback: function(out) {\n spbcReloadAccordion();\n if ( action === 'check_analysis_status' && typeof out !== 'undefined') {\n let html = '
Analysis status updated.' +\n ' Total: ' + out.counters.total +\n ', updated: ' + out.counters.updated +\n ', skipped: ' + out.counters.skipped +\n ', failed: ' + out.counters.failed +\n ', queued: ' + out.counters.queued +\n '
';\n spbcModal.open().put( html );\n }\n if ( action === 'send' && typeof out !== 'undefined') {\n let html = '
Files have been sent: ' +\n out.files_sent_counter +\n '
';\n spbcModal.open().put(html);\n }\n },\n errorOutput: function( errorText, comment ) {\n if ( comment ) {\n errorText = errorText + '
Additional information:
' + comment;\n }\n spbcModal.open().putError( errorText );\n },\n timeout: 60000,\n };\n\n spbcSendAJAXRequest(data, params);\n } else {\n alert('This action is not supported for all files yet =(');\n }\n });\n\n jQuery('.tbl-bulk_actions--apply')\n .off('click')\n .on('click', function(e) {\n let self = spbcBulkAction || jQuery(this);\n spbcBulkAction = self;\n let action = self.siblings('select').children()[self.siblings('select').first()[0].selectedIndex].value;\n\n if (!spbcBulkAction && !noConfirmActions.any.includes(action) && !confirm(spbcTable.warning_bulk)) {\n return;\n }\n\n if (action === 'cure') {\n spbcScannerCureBulk(jQuery(this), false);\n return;\n }\n\n if (action === 'restore') {\n spbcScannerRestoreBulk(jQuery(this), false);\n return;\n }\n\n if (action === 'delete_from_analysis_log') {\n spbcScannerAnalysisLogDeleteFromLog(jQuery(this));\n return;\n }\n\n if (action === 'allow' || action === 'ban') {\n let sendAction = action === 'ban' ? 'deny' : action;\n let items = self.parents('.tbl-root').find('.cb-select:checked');\n if (items) {\n self.children('.tbl-preloader--small').show();\n items.each(function() {\n let ip = jQuery(this).parents('tr').find('.tbl-row_action--'+action).data('ip');\n spbcSecLogsFilterIp(ip, sendAction, true);\n jQuery(this).prop('checked', false);\n });\n }\n self.children('.tbl-preloader--small').hide();\n let msg = action === 'allow' ? 'Allowed' : 'Banned';\n let html = '
Success. Selected IPs have been ' +\n msg +\n '. Changes will be applied within 10 minutes.' +\n '
';\n spbcModal.open().put( html );\n setTimeout(spbcReloadAccordion, 1900);\n\n return;\n }\n\n if ( action !== '-1' && self.parents('.tbl-root').find('.cb-select').is(':checked') ) {\n self.children('.tbl-preloader--small').show();\n // eslint-disable-next-line max-len\n if (self.parents('.tbl-root').find('.cb-select:checked').first().parents('tr').find('.tbl-row_action--'+action)[0]) {\n self\n .parents('.tbl-root')\n .find('.cb-select:checked')\n .first()\n .parents('tr')\n .find('.tbl-row_action--'+action)\n .click();\n self.parents('.tbl-root').find('.cb-select:checked').first().prop('checked', false);\n } else {\n self.parents('.tbl-root').find('.cb-select:checked').first().prop('checked', false);\n self.click();\n }\n } else {\n self.children('.tbl-preloader--small').hide();\n spbcBulkAction = null;\n if ( action === 'check_analysis_status' || action === 'disapprove' ) {\n let html = '
All available files are updated.' + '
';\n spbcModal.open().put( html );\n }\n if ( action === 'send') {\n let html = '
All available files are sent.' + '
';\n spbcModal.open().put( html );\n }\n setTimeout(spbcReloadAccordion, 1900);\n }\n // reset spbcBulkAction if action is restricted\n if (noConfirmActions.restricted.includes(action)) {\n spbcBulkAction = null;\n }\n });\n}\n\n/**\n * Cure selected files\n * @param {obj} current\n * @param {boolean} allItems\n */\nfunction spbcScannerCureBulk(current, allItems = false) {\n let selectedIds = [];\n const selector = allItems ? '.cb-select' : '.cb-select:checked';\n const selectedItems = current.closest('#spbc_tbl__scanner_cure_log').find(selector);\n\n if (selectedItems.length === 0) {\n alert('Please, select elements.');\n return;\n }\n\n selectedItems.each(function(index, element) {\n const elementId = jQuery(element).val();\n selectedIds.push(elementId);\n });\n\n const data = {\n action: 'spbc_cure_selected',\n security: spbcSettings.ajax_nonce,\n selectedIds: selectedIds,\n };\n jQuery.ajax({\n type: 'POST',\n url: spbcSettings.ajaxurl,\n data: data,\n beforeSend: function() {\n current\n .closest('#spbc_tbl__scanner_cure_log')\n .find('.tbl-button---white_blue .tbl-preloader--in_button')\n .show();\n },\n success: function(result) {\n current\n .closest('#spbc_tbl__scanner_cure_log')\n .find('.tbl-button---white_blue .tbl-preloader--in_button')\n .hide();\n const displayData = result.data;\n // prepare output\n let divWrapper = document.createElement('div');\n let pMessage = document.createElement('p');\n let pCounters = document.createElement('p');\n let divFiles = document.createElement('div');\n let bSeeMore = document.createElement('b');\n let pSeeMore = document.createElement('p');\n bSeeMore.innerHTML = 'See more details in the threats log.';\n pSeeMore.append(bSeeMore);\n const failedToCure = displayData.hasOwnProperty('failed_to_cure') ? displayData.failed_to_cure : [];\n if (failedToCure.length > 0) {\n divFiles.innerHTML = failedToCure.join('');\n }\n pMessage.innerHTML = displayData.message;\n pCounters.innerHTML += 'Cured: ' +\n (\n displayData.hasOwnProperty('cured_on_request') ?\n displayData.cured_on_request :\n 0\n );\n pCounters.innerHTML += ', already cured: ' +\n (\n displayData.hasOwnProperty('skipped') ?\n displayData.skipped :\n 0\n );\n pCounters.innerHTML += ', failed to cure: ' + failedToCure.length;\n\n divWrapper.append(pMessage);\n divWrapper.append(pCounters);\n divWrapper.append(divFiles);\n if (failedToCure.length > 0) {\n divWrapper.append(pSeeMore);\n }\n if (result.success) {\n spbcModal.open().put(divWrapper.outerHTML);\n } else {\n spbcModal.open().putError(divWrapper.outerHTML);\n }\n document.addEventListener('spbcModalClosed', function( e ) {\n spbcReloadAccordion();\n });\n },\n });\n}\n\n/**\n * Restore selected files\n * @param {obj} current\n * @param {boolean} allItems\n */\nfunction spbcScannerRestoreBulk(current, allItems = false) {\n let selectedIds = [];\n const selector = allItems ? '.cb-select' : '.cb-select:checked';\n const selectedItems = current.closest('#spbc_tbl__scanner_cure_log').find(selector);\n\n if (selectedItems.length === 0) {\n alert('Please, select elements.');\n return;\n }\n\n selectedItems.each(function(index, element) {\n const elementId = jQuery(element).val();\n selectedIds.push(elementId);\n });\n\n const data = {\n action: 'spbc_restore_selected',\n security: spbcSettings.ajax_nonce,\n selectedIds: selectedIds,\n };\n jQuery.ajax({\n type: 'POST',\n url: spbcSettings.ajaxurl,\n data: data,\n beforeSend: function() {\n current\n .closest('#spbc_tbl__scanner_cure_log')\n .find('.tbl-button---white_blue .tbl-preloader--in_button')\n .show();\n },\n success: function(result) {\n current\n .closest('#spbc_tbl__scanner_cure_log')\n .find('.tbl-button---white_blue .tbl-preloader--in_button')\n .hide();\n const displayData = result.data;\n // prepare output\n let divWrapper = document.createElement('div');\n let pMessage = document.createElement('p');\n let pCounters = document.createElement('p');\n let divFiles = document.createElement('div');\n const failedToRestore = displayData.hasOwnProperty('failed_to_restore') ?\n displayData.failed_to_restore :\n [];\n if (failedToRestore.length > 0) {\n divFiles.innerHTML = failedToRestore.join('');\n }\n pMessage.innerHTML = displayData.message;\n pCounters.innerHTML += 'Restored: ' +\n (\n displayData.hasOwnProperty('restored_on_request') ?\n displayData.restored_on_request :\n 0\n );\n pCounters.innerHTML += ', unchanged or already restored: ' +\n (\n displayData.hasOwnProperty('skipped') ?\n displayData.skipped :\n 0\n );\n pCounters.innerHTML += ', failed to restore: ' + failedToRestore.length;\n\n divWrapper.append(pMessage);\n divWrapper.append(pCounters);\n divWrapper.append(divFiles);\n\n if (result.success) {\n spbcModal.open().put(divWrapper.outerHTML);\n } else {\n spbcModal.open().putError(divWrapper.outerHTML);\n }\n document.addEventListener('spbcModalClosed', function( e ) {\n spbcReloadAccordion();\n });\n },\n });\n}\n\n/**\n * Table row actions\n */\nfunction spbcTblRowActionsListen() {\n jQuery('.tbl-row_action--ajax')\n .off('click')\n .on('click', function() {\n if ( spbcScanner.active ) {\n alert(spbcTableLocalize.scannerIsActive);\n return;\n }\n let self = jQuery(this);\n let data = {\n action: 'spbc_tbl-action--row',\n add_action: self.attr('row-action'),\n id: self.parents('.row-actions').attr('uid'),\n cols: self.parents('.row-actions').attr('cols_amount'),\n page_url: self.parent().attr('uid'),\n page_id: self.parent().attr('page_id'),\n };\n let params = {\n callback: spbcTblRowActionsCallback,\n errorOutput: function(msg, comment, hideSupportLink) {\n spbcModal.open().putError( msg, hideSupportLink );\n },\n spinner: self.parent().siblings('.tbl-preloader--tiny'),\n };\n\n // @ToDo delete this timeout after ready task #10014\n if ( self.attr('row-action') === 'delete' ) {\n params.timeout = 60000;\n }\n\n let fileName = self.parent().parent()[0].firstChild.innerHTML;\n let confirmationHeader = spbcTable['warning_h_'+self.attr('row-action')] || spbcTable.warning_default;\n let confirmationText = spbcTable['warning_t_'+self.attr('row-action')] || '';\n // init row actions with no confirm required\n if ( spbcBulkAction || noConfirmActions.any.includes(data.add_action) ) {\n // do not request user confirmation if the action is excluded or if it is a bulk action\n spbcSendAJAXRequest(data, params, self.parents('tr'));\n } else {\n // do request confirmation otherwise\n const yesButtonText = self.attr('row-action') === 'quarantine' ? 'Quarantine' : 'Yes';\n const noButtonText = self.attr('row-action') === 'quarantine' ? 'Cancel' : 'No';\n spbcModal.open().confirm(confirmationHeader, confirmationText, fileName, (confirmed) => {\n if (confirmed) {\n spbcSendAJAXRequest(data, params, self.parents('tr'));\n }\n }, yesButtonText, noButtonText);\n }\n });\n}\n\n/**\n * Row actions with no confirm required.\n * @param {object} spbcPublic Global localized SPBC object\n * @return {{}}\n */\nfunction spbcGetNoConfirmActions(spbcPublic) {\n let noConfirmActionsEmpty = {\n 'any': [],\n 'restricted': [],\n 'defaults': [],\n };\n let noConfirmActions = noConfirmActionsEmpty;\n try {\n if ( typeof spbcPublic !== 'undefined' && spbcPublic.hasOwnProperty('no_confirm_row_actions')) {\n noConfirmActions = JSON.parse(spbcPublic.no_confirm_row_actions);\n }\n if (\n typeof noConfirmActions.any.includes !== 'function' ||\n typeof noConfirmActions.restricted.includes !== 'function' ||\n typeof noConfirmActions.defaults.includes !== 'function'\n ) {\n noConfirmActions = noConfirmActionsEmpty;\n }\n } catch (e) {\n noConfirmActions = noConfirmActionsEmpty;\n }\n return noConfirmActions;\n}\n\n/**\n * Callback for table row actions\n *\n * @param {obj|string} result\n * @param {obj} data\n * @param {obj} params\n * @param {obj} obj\n */\nfunction spbcTblRowActionsCallback(result, data, params, obj) {\n if (result.color) {\n obj.css({background: result.background, color: result.color});\n }\n if (result.html) {\n obj.parent().parent().parent().prepend(result.html);\n setTimeout(function() {\n obj.fadeOut(300);\n }, 1500);\n if ( ! spbcBulkAction) {\n setTimeout(spbcReloadAccordion, 1900);\n }\n }\n\n if (\n data.add_action === 'copy_file_info'\n ) {\n if (result.success === true && result.data.file_info) {\n window.\n prompt('Copy the file info below and send it to support@cleantalk.org: ', result.data.file_info);\n } else {\n let errorText = (typeof result.data.error !== 'undefined') ?\n result.data.error :\n 'Unknown copy_file_info error';\n spbcModal.open().putError( errorText );\n }\n }\n\n if (result.temp_html) {\n let tmp=obj.html();\n obj.html(result.temp_html);\n if (result.updated_template !== undefined) {\n let updatedType = result.updated_template_type;\n let template = result.updated_template;\n let rowsInTemplate = jQuery(template).find('.wp-list-table tbody tr');\n let countRowInTemplate = rowsInTemplate.length;\n let targetTab = jQuery('[aria-controls=\"spbc_scan_accordion_tab_' + updatedType + '\"]');\n\n if (targetTab.length > 0) {\n let table = jQuery('#spbc_tbl__scanner_' + updatedType);\n // Count files in header\n jQuery('.spbc_bad_type_count.' + updatedType + '_counter').text(countRowInTemplate);\n // Count rows in table\n let countExistingRows = table.find('.wp-list-table tbody tr').length;\n table.remove();\n jQuery('#spbc_scan_accordion_tab_' + updatedType).append(template);\n // Marked new rows\n jQuery(jQuery('#spbc_scan_accordion_tab_' + updatedType)\n .find('.wp-list-table tbody tr'))\n .each(function(index, element) {\n if (++index > countExistingRows) {\n jQuery(element).css('outline', '1px solid green');\n }\n });\n targetTab.click();\n } else {\n if (updatedType === 'analysis_log') {\n // eslint-disable-next-line max-len\n let tabHeaderTemplate = '';\n // eslint-disable-next-line max-len\n let tabBodyTemplate = '
Files sent for analysis.
' +\n template +\n '
';\n jQuery('#spbc_scan_accordion_tab_critical').after(tabHeaderTemplate + tabBodyTemplate);\n targetTab.click();\n }\n }\n }\n setTimeout(function() {\n obj\n .html(tmp)\n .css({background: 'inherit'})\n .find('.column-primary .row-actions .tbl-row_action--' + data.add_action)\n .remove();\n spbcTblBulkActionsListen();\n spbcTblRowActionsListen();\n spbcStartShowHide();\n }, 5000);\n }\n if (spbcBulkAction) {\n spbcBulkAction.click();\n }\n}\n\n/**\n * Table pagination actions\n */\nfunction spbcTblPaginationListen() {\n let data = {action: 'spbc_tbl-pagination'};\n let params = {callback: spbcTblPaginationCallback, notJson: true};\n jQuery('.tbl-pagination--button').on('click', function() {\n jQuery(this).parents('.tbl-root').find('.tbl-pagination--button').attr('disabled', 'disabled');\n });\n jQuery('.tbl-pagination--go').on('click', function() {\n let self = jQuery(this);\n let obj = self.parents('.tbl-root');\n data.page = self.siblings('.tbl-pagination--curr_page').val();\n data.type = obj.attr('type');\n params.spinner = self.siblings('.tbl-preloader--small');\n spbcSendAJAXRequest(data, params, obj);\n });\n jQuery('.tbl-pagination--prev').on('click', function() {\n let self = jQuery(this);\n let obj = self.parents('.tbl-root');\n data.page = self.parents('.tbl-pagination--wrapper').attr('prev_page');\n data.type = obj.attr('type');\n params.spinner = self.siblings('.tbl-preloader--small');\n spbcSendAJAXRequest(data, params, obj);\n });\n jQuery('.tbl-pagination--next').on('click', function() {\n let self = jQuery(this);\n let obj = self.parents('.tbl-root');\n data.page = self.parents('.tbl-pagination--wrapper').attr('next_page');\n data.type = obj.attr('type');\n params.spinner = self.siblings('.tbl-preloader--small');\n spbcSendAJAXRequest(data, params, obj);\n });\n jQuery('.tbl-pagination--end').on('click', function() {\n let self = jQuery(this);\n let obj = self.parents('.tbl-root');\n data.page = self.parents('.tbl-pagination--wrapper').attr('last_page');\n data.type = obj.attr('type');\n params.spinner = self.siblings('.tbl-preloader--small');\n spbcSendAJAXRequest(data, params, obj);\n });\n jQuery('.tbl-pagination--start').on('click', function() {\n let self = jQuery(this);\n let obj = self.parents('.tbl-root');\n data.page = 1;\n data.type = obj.attr('type');\n params.spinner = self.siblings('.tbl-preloader--small');\n spbcSendAJAXRequest(data, params, obj);\n });\n}\n\n/**\n * Callback for Table pagination actions\n *\n * @param {obj|string} result\n * @param {obj} data\n * @param {obj} params\n * @param {obj} obj\n */\nfunction spbcTblPaginationCallback(result, data, params, obj) {\n jQuery(obj)\n .html(result)\n .find('.tbl-pagination--button').removeAttr('disabled');\n spbcTblBulkActionsListen();\n spbcTblRowActionsListen();\n spbcTblPaginationListen();\n spbcTblSortListen();\n spbcStartShowHide();\n}\n\n/**\n * Table sort actions\n */\nfunction spbcTblSortListen() {\n let params = {callback: spbcTblSortCallback, notJson: true};\n jQuery('.tbl-column-sortable').on('click', function(e) {\n if (e.target.classList.contains('tbl-sorting_indicator')) {\n let self = jQuery(this);\n let obj = self.parents('.tbl-root');\n let domain = obj.attr('type') == 'links'? jQuery('#spbc_tbl__scanner__outbound_links b').html(): '';\n let data = {\n action: 'spbc_tbl-sort',\n order_by: self.attr('id'),\n order: self.attr('sort_direction'),\n type: obj.attr('type'),\n domain: domain,\n };\n spbcSendAJAXRequest(data, params, obj);\n }\n });\n}\n\n/**\n * Callback for Table sort actions\n *\n * @param {obj|string} result\n * @param {obj} data\n * @param {obj} params\n * @param {obj} obj\n */\nfunction spbcTblSortCallback(result, data, params, obj) {\n jQuery(obj).html(result);\n spbcTblBulkActionsListen();\n spbcTblRowActionsListen();\n spbcTblPaginationListen();\n spbcTblSortListen();\n}\n\njQuery(document).ready(function() {\n // Table. Row actions handler\n spbcTblBulkActionsListen();\n spbcTblRowActionsListen();\n spbcTblPaginationListen();\n spbcTblSortListen();\n spbcEATUpdateIntervalStart();\n});\n\n/**\n * Switching table handler\n * Using by inline php code\n *\n * @param {obj} obj\n * @param {obj} table\n *\n */\nfunction spbcScannerSwitchTable(obj, table) {/* eslint-disable-line no-unused-vars */\n let _obj = jQuery(obj);\n let domain = _obj.parents('.row-actions').attr('uid');\n let data = {action: 'spbc_tbl-switch', type: table, domain: domain};\n let params = {callback: spbcTblPaginationCallback, notJson: true};\n spbcSendAJAXRequest(data, params, _obj.parents('.tbl-root'));\n}\n\n/**\n * Open/close table rows handler\n * Using by inline php code\n *\n * @param {string} blockId\n * @param {string} columnKey\n */\nfunction spbcShowHideRows(blockId, columnKey) {/* eslint-disable-line no-unused-vars */\n let className = '.' + columnKey + '_block_' + blockId;\n let block = jQuery(className);\n if (block.hasClass('mob_table_active')) {\n block.removeClass('mob_table_active');\n } else {\n block.addClass('mob_table_active');\n }\n}\n\n/**\n * Starts an interval to update the analysis log table and stats every 6 seconds.\n */\nfunction spbcEATUpdateIntervalStart() {\n setInterval(() => {\n // Check if the analysis log tab is present\n if (document.querySelector('div[refresh_control_tab=\"analysis_log\"]') !== null) {\n // Add a spinner to the analysis log tab header\n spbcEATAddSpinner();\n // Update the analysis log table\n spbcUpdateTableEAT();\n // Update the analysis log stats\n spbcUpdateStatsEAT();\n }\n }, 60000);\n}\n\n/**\n * Adds a spinner to the analysis log tab header if it doesn't already exist.\n */\nfunction spbcEATAddSpinner() {\n if (document.getElementById('analysis_log_counter_spinner') === null) {\n const refreshTab = document.querySelector('h3[aria-controls=\"spbc_scan_accordion_tab_analysis_log\"]');\n if (refreshTab !== null) {\n const spinner = document.createElement('img');\n spinner.class = 'spbc_preloader';\n // todo Probably we need a validation function of spbcSettings object\n spinner.alt = spbcSettings.spbcSpinner.altText;\n spinner.src = spbcSettings.spbcSpinner.imgSource;\n spinner.id = 'analysis_log_counter_spinner';\n spinner.style = 'display: none; height: 13px; position: relative; top: 2px; margin-left: 5px';\n refreshTab.append(spinner);\n }\n }\n spbcEATSwitchSpinner();\n}\n\n/**\n * Toggles the display of the spinner in the analysis log tab header.\n */\nfunction spbcEATSwitchSpinner() {\n const spinner = document.getElementById('analysis_log_counter_spinner');\n if (spinner !== null) {\n spinner.style.display = spinner.style.display === 'none' ?\n spinner.style.display = 'inline' :\n spinner.style.display = 'none';\n }\n}\n\n/**\n * Sends an AJAX request to update the analysis log table.\n */\nfunction spbcUpdateTableEAT() {\n // Define the tab name for the request\n let tabName = 'scanner';\n // Data object containing parameters for the AJAX request\n let data = {\n action: 'spbc_settings__draw_elements',\n tab_name: tabName,\n security: spbcSettings.ajax_nonce,\n };\n // Params object with additional settings for the AJAX request\n let currentParams = {\n callback: spbcUpdateTableCallbackEAT,\n notJson: true,\n additional: null,\n };\n // Send the AJAX request with the data and params objects\n spbcSendAJAXRequest( data, currentParams, null );\n}\n\n/**\n * Callback function to update the analysis log table with new HTML content.\n *\n * @param {string} allTablesHTML - The HTML content of all tables.\n */\nfunction spbcUpdateTableCallbackEAT(allTablesHTML) {\n // select the same table element to search in the current code and update from received\n const analysisTableSelector = '#spbc_tbl__scanner_analysis_log';\n const parser = new DOMParser();\n const allTablesHTMLParsed = parser.parseFromString(allTablesHTML, 'text/html');\n\n let newTabElement = null;\n let newTabElementInnerHTML = '';\n let currentTabElement = null;\n\n // get new analysis table element and its HTML\n newTabElement = allTablesHTMLParsed.querySelector(analysisTableSelector);\n if (newTabElement !== null && newTabElement.innerHTML !== '') {\n newTabElementInnerHTML = newTabElement.innerHTML;\n }\n\n // get current analysis table element and its HTML\n currentTabElement = document.querySelector(analysisTableSelector);\n if (currentTabElement !== null && currentTabElement.innerHTML === '') {\n currentTabElement = null;\n }\n\n // update analysis table element if it's changed and new data presented\n if (currentTabElement !== null && newTabElementInnerHTML !== '') {\n currentTabElement.innerHTML = newTabElementInnerHTML;\n }\n}\n\n/**\n * Sends an AJAX request to update the analysis log stats.\n */\nfunction spbcUpdateStatsEAT() {\n // Data object containing parameters for the AJAX request\n let data = {\n action: 'spbc_analysyis_files_stats__get_html',\n sub_action: 'give_me_html',\n security: spbcSettings.ajax_nonce,\n };\n // Params object with additional settings for the AJAX request\n let params = {\n callback: spbcUpdateStatsCallbackEAT,\n notJson: true,\n };\n // Send the AJAX request with the data and params objects\n spbcSendAJAXRequest(data, params);\n}\n\n/**\n * Callback function to update the analysis log stats with new HTML content.\n *\n * @param {string} newStatsHtml - The new HTML content for the stats.\n */\nfunction spbcUpdateStatsCallbackEAT(newStatsHtml) {\n // Get the element that displays the analysis files stats\n let info = document.getElementById('spbc_analysis_files_stats');\n // If the element exists, update its inner HTML with the new stats\n if (info) {\n info.innerHTML = newStatsHtml;\n }\n // Toggle the display of the spinner in the analysis log tab header\n spbcEATSwitchSpinner();\n}\n"],"names":["let","spbcBulkAction","noConfirmActions","spbcGetNoConfirmActions","spbcPublic","spbcReloadAccordion","interactControlTab","updateText","spbcSendAJAXRequest","action","notJson","callback","result","data","params","obj","jQuery","accordion","html","header","heightStyle","collapsible","active","spbcTblBulkActionsListen","spbcTblRowActionsListen","spbcTblPaginationListen","spbcTblSortListen","spbcStartShowHide","interactScannerTab","controlTab","refreshControlTabSelector","headerUpdateStatus","headerSelector","appendTo","click","setAttribute","hide","off","on","spbcScanner","alert","spbcTableLocalize","scannerIsActive","self","this","siblings","children","first","selectedIndex","value","indexOf","any","includes","confirm","spbcTable","warning_bulk","add_action","status","parents","attr","spbcScannerCureBulk","spbcScannerRestoreBulk","selectedItems","closest","find","fileIds","each","index","element","elementId","val","push","file_ids","button","spinner","out","counters","total","updated","skipped","failed","queued","spbcModal","open","put","files_sent_counter","errorOutput","errorText","comment","putError","timeout","e","spbcScannerAnalysisLogDeleteFromLog","sendAction","items","msg","show","ip","spbcSecLogsFilterIp","prop","setTimeout","is","restricted","current","allItems","selectedIds","selector","length","security","spbcSettings","ajax_nonce","ajax","type","url","ajaxurl","beforeSend","success","displayData","divWrapper","document","createElement","pMessage","pCounters","divFiles","bSeeMore","pSeeMore","failedToCure","innerHTML","append","hasOwnProperty","failed_to_cure","join","message","cured_on_request","outerHTML","addEventListener","failedToRestore","failed_to_restore","restored_on_request","id","cols","page_url","parent","page_id","spbcTblRowActionsCallback","hideSupportLink","yesButtonText","noButtonText","fileName","firstChild","confirmationHeader","warning_default","confirmationText","confirmed","noConfirmActionsEmpty","defaults","JSON","parse","no_confirm_row_actions","color","css","background","prepend","fadeOut","file_info","window","prompt","error","temp_html","tmp","undefined","updated_template","updatedType","updated_template_type","template","countRowInTemplate","targetTab","table","text","countExistingRows","remove","tabHeaderTemplate","tabBodyTemplate","after","spbcTblPaginationCallback","page","removeAttr","spbcTblSortCallback","domain","target","classList","contains","order_by","order","spbcScannerSwitchTable","_obj","spbcShowHideRows","blockId","columnKey","block","hasClass","removeClass","addClass","spbcEATUpdateIntervalStart","setInterval","querySelector","spbcEATAddSpinner","spbcUpdateTableEAT","spbcUpdateStatsEAT","refreshTab","getElementById","class","alt","spbcSpinner","altText","src","imgSource","style","spbcEATSwitchSpinner","display","tab_name","spbcUpdateTableCallbackEAT","additional","allTablesHTML","analysisTableSelector","newTabElementInnerHTML","currentTabElement","newTabElement","DOMParser","parseFromString","sub_action","spbcUpdateStatsCallbackEAT","newStatsHtml","info","ready"],"mappings":"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"}
\ No newline at end of file
diff --git a/js/src/spbc-table.js b/js/src/spbc-table.js
index cac29831..0d89123e 100644
--- a/js/src/spbc-table.js
+++ b/js/src/spbc-table.js
@@ -133,14 +133,7 @@ function spbcTblBulkActionsListen() {
}
if (action === 'restore') {
- const selectedItems = self.closest('#spbc_tbl__scanner_cure_log').find('.cb-select');
- let selectedIds = [];
-
- selectedItems.each(function(index, element) {
- const elementId = jQuery(element).val();
- selectedIds.push(elementId);
- });
- data.selectedIds = selectedIds;
+ spbcScannerRestoreBulk(self, true);
}
if (action === 'delete_from_analysis_log') {
@@ -208,7 +201,7 @@ function spbcTblBulkActionsListen() {
}
if (action === 'restore') {
- spbcScannerRestoreSelected(jQuery(this));
+ spbcScannerRestoreBulk(jQuery(this), false);
return;
}
@@ -322,6 +315,10 @@ function spbcScannerCureBulk(current, allItems = false) {
let pMessage = document.createElement('p');
let pCounters = document.createElement('p');
let divFiles = document.createElement('div');
+ let bSeeMore = document.createElement('b');
+ let pSeeMore = document.createElement('p');
+ bSeeMore.innerHTML = 'See more details in the threats log.';
+ pSeeMore.append(bSeeMore);
const failedToCure = displayData.hasOwnProperty('failed_to_cure') ? displayData.failed_to_cure : [];
if (failedToCure.length > 0) {
divFiles.innerHTML = failedToCure.join('');
@@ -344,6 +341,9 @@ function spbcScannerCureBulk(current, allItems = false) {
divWrapper.append(pMessage);
divWrapper.append(pCounters);
divWrapper.append(divFiles);
+ if (failedToCure.length > 0) {
+ divWrapper.append(pSeeMore);
+ }
if (result.success) {
spbcModal.open().put(divWrapper.outerHTML);
} else {
@@ -359,13 +359,16 @@ function spbcScannerCureBulk(current, allItems = false) {
/**
* Restore selected files
* @param {obj} current
+ * @param {boolean} allItems
*/
-function spbcScannerRestoreSelected(current) {
- const selectedItems = current.closest('#spbc_tbl__scanner_cure_log').find('.cb-select:checked');
+function spbcScannerRestoreBulk(current, allItems = false) {
let selectedIds = [];
+ const selector = allItems ? '.cb-select' : '.cb-select:checked';
+ const selectedItems = current.closest('#spbc_tbl__scanner_cure_log').find(selector);
if (selectedItems.length === 0) {
alert('Please, select elements.');
+ return;
}
selectedItems.each(function(index, element) {
@@ -393,14 +396,45 @@ function spbcScannerRestoreSelected(current) {
.closest('#spbc_tbl__scanner_cure_log')
.find('.tbl-button---white_blue .tbl-preloader--in_button')
.hide();
+ const displayData = result.data;
+ // prepare output
+ let divWrapper = document.createElement('div');
+ let pMessage = document.createElement('p');
+ let pCounters = document.createElement('p');
+ let divFiles = document.createElement('div');
+ const failedToRestore = displayData.hasOwnProperty('failed_to_restore') ?
+ displayData.failed_to_restore :
+ [];
+ if (failedToRestore.length > 0) {
+ divFiles.innerHTML = failedToRestore.join('');
+ }
+ pMessage.innerHTML = displayData.message;
+ pCounters.innerHTML += 'Restored: ' +
+ (
+ displayData.hasOwnProperty('restored_on_request') ?
+ displayData.restored_on_request :
+ 0
+ );
+ pCounters.innerHTML += ', unchanged or already restored: ' +
+ (
+ displayData.hasOwnProperty('skipped') ?
+ displayData.skipped :
+ 0
+ );
+ pCounters.innerHTML += ', failed to restore: ' + failedToRestore.length;
+
+ divWrapper.append(pMessage);
+ divWrapper.append(pCounters);
+ divWrapper.append(divFiles);
+
if (result.success) {
- spbcModal.open().put(result.data);
- document.addEventListener('spbcModalClosed', function( e ) {
- document.location.reload();
- });
+ spbcModal.open().put(divWrapper.outerHTML);
} else {
- spbcModal.open().putError(result.data);
+ spbcModal.open().putError(divWrapper.outerHTML);
}
+ document.addEventListener('spbcModalClosed', function( e ) {
+ spbcReloadAccordion();
+ });
},
});
}
diff --git a/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/Variables.php b/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/Variables.php
index d5dcaee3..b5ad11d5 100644
--- a/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/Variables.php
+++ b/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/Variables.php
@@ -569,7 +569,11 @@ public function replaceArrayVars($_key)
$this->tokens->searchForward($this->tokens[$var_first_declaration][3], ';') - 1
);
- if ( ! isset($var_expression[2][1][$this->tokens->next2->value + 1]) ) {
+ if (
+ !isset($this->tokens->next2->value) ||
+ !is_numeric($this->tokens->next2->value) ||
+ ! isset($var_expression[2][1][$this->tokens->next2->value + 1])
+ ) {
return;
}
diff --git a/lib/CleantalkSP/Fpdf/Pdf.php b/lib/CleantalkSP/Fpdf/Pdf.php
index fa104a89..e3e83787 100755
--- a/lib/CleantalkSP/Fpdf/Pdf.php
+++ b/lib/CleantalkSP/Fpdf/Pdf.php
@@ -270,7 +270,7 @@ public function drawFilesListByType($type)
// Data
foreach ($data as $row) {
$this->Cell($widths[0], 6, '..' . substr($row['real_path'], $widths[0] * -1), 1);
- $this->Cell($widths[1], 6, $row['cured'], '1', 0, 'C');
+ $this->Cell($widths[1], 6, $row['cure_status'], '1', 0, 'C');
$this->Cell($widths[2], 6, $row['last_cure_date'], '1', 0, 'R');
$this->Cell($widths[3], 6, $row['cci_cured'], '1', 0, 'C');
$this->Ln();
diff --git a/lib/CleantalkSP/SpbctWP/DB/SQLSchema.php b/lib/CleantalkSP/SpbctWP/DB/SQLSchema.php
index d174590f..6748a7b2 100644
--- a/lib/CleantalkSP/SpbctWP/DB/SQLSchema.php
+++ b/lib/CleantalkSP/SpbctWP/DB/SQLSchema.php
@@ -218,6 +218,7 @@ class SQLSchema extends \CleantalkSP\Common\DB\SQLSchema
array('field' => 'backup_id', 'type' => 'int unsigned', 'null' => 'no',),
array('field' => 'real_path', 'type' => 'varchar(512)', 'null' => 'no',),
array('field' => 'back_path', 'type' => 'varchar(512)', 'null' => 'no',),
+ array('field' => 'backup_prev_results_state', 'type' => 'varchar(2048)', 'null' => 'no',),
),
'indexes' => array(
array('type' => 'PRIMARY', 'name' => 'KEY', 'body' => '(`id`)'),
@@ -252,11 +253,12 @@ class SQLSchema extends \CleantalkSP\Common\DB\SQLSchema
array('field' => 'full_hash', 'type' => 'char(32)', 'null' => 'no'),
array('field' => 'cured_hash', 'type' => 'char(32)', 'null' => 'no'),
array('field' => 'real_path', 'type' => 'varchar(512)', 'null' => 'no'),
- array('field' => 'cured', 'type' => 'tinyint', 'null' => 'no',),
+ array('field' => 'cure_status', 'type' => 'tinyint', 'null' => 'no',),
array('field' => 'weak_spots_cured', 'type' => 'varchar(512)', 'null' => 'no',),
array('field' => 'weak_spots_uncured', 'type' => 'varchar(512)', 'null' => 'no',),
- array('field' => 'has_backup', 'type' => 'tinyint', 'null' => 'no',),
- array('field' => 'cci_cured', 'type' => 'tinyint', 'null' => 'yes', 'default' => 'NULL'),
+ array('field' => 'has_backup', 'type' => 'tinyint', 'null' => 'no', 'default' => 0),
+ array('field' => 'cci_cured', 'type' => 'tinyint', 'null' => 'no', 'default' => 0),
+ array('field' => 'is_restored', 'type' => 'tinyint', 'null' => 'no', 'default' => 0),
array('field' => 'fail_reason', 'type' => 'varchar(512)', 'null' => 'yes', 'default' => 'NULL'),
array('field' => 'last_cure_date', 'type' => 'int', 'null' => 'no',),
array('field' => 'scanner_start_local_date', 'type' => 'datetime', 'null' => 'no',),
diff --git a/lib/CleantalkSP/SpbctWP/ListTable.php b/lib/CleantalkSP/SpbctWP/ListTable.php
index 4c4e4726..87ba174d 100644
--- a/lib/CleantalkSP/SpbctWP/ListTable.php
+++ b/lib/CleantalkSP/SpbctWP/ListTable.php
@@ -580,7 +580,8 @@ public static function ajaxBulkActionHandler()
Cure::cureSelectedAction();
break;
case 'restore':
- $out = Cure::restoreSelectedAction();
+ //this method has own ajax handler
+ Cure::restoreSelectedAction();
break;
case 'delete_from_analysis_log':
$out = spbc_scanner_analysis_log_delete_from_log(true);
diff --git a/lib/CleantalkSP/SpbctWP/Scanner/Cure.php b/lib/CleantalkSP/SpbctWP/Scanner/Cure.php
index 4f2e82d6..d92f972e 100644
--- a/lib/CleantalkSP/SpbctWP/Scanner/Cure.php
+++ b/lib/CleantalkSP/SpbctWP/Scanner/Cure.php
@@ -2,8 +2,7 @@
namespace CleantalkSP\SpbctWP\Scanner;
-use CleantalkSP\SpbctWP\DB;
-use CleantalkSP\SpbctWP\Scanner\Stages\CureStage;
+use CleantalkSP\SpbctWP\Scanner\CureLog\CureLog;
class Cure
{
@@ -44,7 +43,7 @@ public function __construct($file)
$this->weak_spots_result[$counter] = array(
'weak_spots_file_line' => $_string,
'signature_id' => '',
- 'cured' => 0,
+ 'weakspot_is_cured' => 0,
'error' => ''
);
foreach ( $signatures_in_string as $signature_id ) {
@@ -55,7 +54,7 @@ public function __construct($file)
);
$this->signature = $tmp[0];
$result = $this->signatureCure($file, $this->signature, $this->weak_spots_result[$counter]);
- $this->weak_spots_result[$counter]['cured'] = (int)$result;
+ $this->weak_spots_result[$counter]['weakspot_is_cured'] = (int)$result;
}
$counter++;
}
@@ -284,7 +283,12 @@ public static function cureSelectedAction()
{
spbc_check_ajax_referer('spbc_secret_nonce', 'security');
- $ids = $_POST['selectedIds'];
+ $ids = isset($_POST['selectedIds']) ? $_POST['selectedIds'] : null;
+
+ if (empty($ids)) {
+ $response_data['message'] = esc_html__('No items to restore', 'security-malware-firewall');
+ wp_send_json_error($response_data);
+ }
$cured_on_request = 0;
$failed_to_cure = array();
$skipped = 0;
@@ -295,12 +299,7 @@ public static function cureSelectedAction()
'failed_to_cure' => $failed_to_cure,
);
- if (empty($ids)) {
- $response_data['message'] = esc_html__('No items for cure', 'security-malware-firewall');
- wp_send_json_error($response_data);
- }
-
- $cure_stage = new CureStage(DB::getInstance());
+ $cure_stage = new CureLog();
$cured_files = $cure_stage->getCuredFilesFastHashes();
$cured_fast_hashes = array_column($cured_files, 'fast_hash');
$to_cure = array_diff($ids, $cured_fast_hashes);
@@ -342,19 +341,60 @@ public static function restoreSelectedAction()
{
spbc_check_ajax_referer('spbc_secret_nonce', 'security');
- if (empty($_POST['selectedIds'])) {
- wp_send_json_error(esc_html__('No items for checking', 'security-malware-firewall'));
+ $ids = isset($_POST['selectedIds']) ? $_POST['selectedIds'] : null;
+
+ if (empty($ids)) {
+ $response_data['message'] = esc_html__('No items to restore', 'security-malware-firewall');
+ wp_send_json_error($response_data);
+ }
+
+ $restored_on_request = 0;
+ $failed_to_restore = array();
+ $skipped = 0;
+ $response_data = array(
+ 'message' => esc_html__('Success!', 'security-malware-firewall'),
+ 'restored_on_request' => $restored_on_request,
+ 'skipped' => $skipped,
+ 'failed_to_restore' => $failed_to_restore,
+ );
+
+ $cure_log = new CureLog();
+ $restored_fast_hashes = $cure_log->getRestoredFiles(true);
+ $restored_fast_hashes = array_column($restored_fast_hashes, 'fast_hash');
+ $to_restore = array_diff($ids, $restored_fast_hashes);
+ if (empty($to_restore)) {
+ $response_data['message'] = esc_html__('All selected files are already restored.', 'security-malware-firewall');
+ wp_send_json_success($response_data);
}
- $file_fast_hashes = isset($_POST['selectedIds']) ? esc_sql($_POST['selectedIds']) : null;
+ $totally_failed_files_fast_hashes = $cure_log->getTotallyFailedFilesFastHashes();
+ $totally_failed_files_fast_hashes = array_column($totally_failed_files_fast_hashes, 'fast_hash');
+ $to_restore = array_diff($to_restore, $totally_failed_files_fast_hashes);
- foreach ($file_fast_hashes as $file_fast_hash) {
- $result = spbc_restore_file_from_backup_ajax_action_handler($file_fast_hash);
- if (isset($result['error'])) {
- wp_send_json_error($result['error']);
+ $skipped = count($ids) - count($to_restore);
+
+ foreach ($to_restore as $id) {
+ $id = sanitize_user($id, true);
+ $result = spbc_restore_file_from_backup_ajax_action_handler($id);
+ if ($result['success'] !== true) {
+ $path = spbc_scanner_get_file_by_id($id);
+ $path = isset($path['path']) ? $path['path'] : 'unknown';
+ $path = '..' . esc_html(substr($path, -50));
+ $failed_to_restore[] = $path . ' - ' . !empty($result['error']) ? $result['error'] : __('Unknown error', 'security-malware-firewall');
+ } else {
+ $restored_on_request++;
}
}
- wp_send_json_success(esc_html__('Success!', 'security-malware-firewall'));
+ $response_data['restored_on_request'] = $restored_on_request;
+ $response_data['skipped'] = $skipped;
+ $response_data['failed_to_restore'] = $failed_to_restore;
+
+ if (count($failed_to_restore) === 0) {
+ wp_send_json_success($response_data);
+ } else {
+ $response_data['message'] = esc_html__('Some files were not restored.', 'security-malware-firewall');
+ wp_send_json_error($response_data);
+ }
}
}
diff --git a/lib/CleantalkSP/SpbctWP/Scanner/CureLog/CureLog.php b/lib/CleantalkSP/SpbctWP/Scanner/CureLog/CureLog.php
index 44b4deae..cd671b36 100644
--- a/lib/CleantalkSP/SpbctWP/Scanner/CureLog/CureLog.php
+++ b/lib/CleantalkSP/SpbctWP/Scanner/CureLog/CureLog.php
@@ -21,22 +21,12 @@ public function __construct()
*/
public function getCountData()
{
+ //do not skip restored files!
$query = 'SELECT COUNT(*) as cnt FROM ' . SPBC_TBL_CURE_LOG;
$result = $this->db->fetch($query);
return (int)$result->cnt;
}
- /**
- * Check if there is failed cure tries
- * @return bool
- */
- public function hasFailedCureTries()
- {
- $query = 'SELECT COUNT(*) as cnt FROM ' . SPBC_TBL_CURE_LOG . ' WHERE cured <> 1';
- $result = $this->db->fetch($query);
- return (bool)$result->cnt;
- }
-
/**
* Returns cure log data for scanner accordion tab
* @return array|object
@@ -45,7 +35,18 @@ public function getDataToAccordion($offset = 0, $amount = 20)
{
$offset = intval($offset);
$amount = intval($amount);
- $query = 'SELECT fast_hash, real_path, cured, cci_cured, weak_spots_cured, weak_spots_uncured, has_backup, fail_reason, last_cure_date FROM ' . SPBC_TBL_CURE_LOG . ' ORDER BY cured LIMIT ' . $offset . ',' . $amount . ';';
+ $query = '
+ SELECT fast_hash,
+ real_path,
+ cure_status,
+ cci_cured,
+ weak_spots_cured,
+ weak_spots_uncured,
+ has_backup,
+ fail_reason,
+ last_cure_date,
+ is_restored
+ FROM ' . SPBC_TBL_CURE_LOG . ' ORDER BY is_restored DESC, cure_status LIMIT ' . $offset . ',' . $amount . ';';
$result = $this->db->fetchAll($query, OBJECT);
if ( empty($result) ) {
@@ -53,16 +54,20 @@ public function getDataToAccordion($offset = 0, $amount = 20)
}
foreach ($result as $row) {
- if ( isset($row->cured) ) {
- if ( $row->cured == '1' ) {
- $row->cured = 'CURED';
- } else if ( $row->cured == '0' ) {
- $row->cured = 'FAILED';
+ if ( isset($row->cure_status) ) {
+ if ( $row->cure_status == '1' ) {
+ $row->cure_status = 'CURED';
+ } else if ( $row->cure_status == '0' ) {
+ $row->cure_status = 'FAILED';
} else {
- $row->cured = 'PARTIALLY CURED';
+ $row->cure_status = 'PARTIALLY CURED';
}
}
+ if (isset($row->is_restored) && $row->is_restored == 1) {
+ $row->cure_status = 'RESTORED';
+ }
+
if ( !empty($row->weak_spots_cured) && is_string($row->weak_spots_cured) ) {
$template = '
';
$template .= self::getThreatTemplate($row->weak_spots_cured, true);
@@ -78,7 +83,7 @@ public function getDataToAccordion($offset = 0, $amount = 20)
$template .= '
';
$row->weak_spots_uncured = $template;
} else {
- $row->weak_spots_uncured = '-';
+ $row->weak_spots_uncured = !empty($row->fail_reason) ? $row->fail_reason : '-';
}
if ( !empty($row->last_cure_date) ) {
@@ -139,7 +144,7 @@ private static function getThreatTemplate($weak_spots_json, $is_cured = true)
*/
public function getDataToPDF()
{
- $query = 'SELECT real_path, cured, cci_cured, last_cure_date
+ $query = 'SELECT real_path, cure_status, cci_cured, last_cure_date
FROM ' . SPBC_TBL_CURE_LOG;
$result = $this->db->fetchAll($query, ARRAY_A);
@@ -148,13 +153,13 @@ public function getDataToPDF()
}
foreach ($result as &$row) {
- if ( isset($row->cured) ) {
- if ( $row->cured == '1' ) {
- $row['cured'] = 'CURED';
- } else if ( $row->cured === '0' ) {
- $row['cured'] = 'FAILED';
+ if ( isset($row->cure_status) ) {
+ if ( $row->cure_status == '1' ) {
+ $row['cure_status'] = 'CURED';
+ } else if ( $row->cure_status === '0' ) {
+ $row['cure_status'] = 'FAILED';
} else {
- $row['cured'] = 'PARTIALLY CURED';
+ $row['cure_status'] = 'PARTIALLY CURED';
}
}
@@ -182,10 +187,25 @@ public function logCureResult(CureLogRecord $cure_log_record)
$this->db->prepare(
'INSERT INTO ' . SPBC_TBL_CURE_LOG
- . ' (`fast_hash`, `full_hash`, `cured_hash`, `real_path`, `cured`, `weak_spots_cured`, `weak_spots_uncured`, `cci_cured`, `has_backup`,`fail_reason`, `last_cure_date`, `scanner_start_local_date`) VALUES'
- . "(%s, %s, %s, %s, %d, %s, %s, %d, %d, %s, %d, %s)"
+ . ' ('
+ . '`fast_hash`, '
+ . '`full_hash`, '
+ . '`cured_hash`, '
+ . '`real_path`, '
+ . '`cure_status`, '
+ . '`is_restored`, '
+ . '`weak_spots_cured`, '
+ . '`weak_spots_uncured`, '
+ . '`cci_cured`, '
+ . '`has_backup`, '
+ . '`fail_reason`, '
+ . '`last_cure_date`, '
+ . '`scanner_start_local_date`
+ ) VALUES'
+ . "(%s, %s, %s, %s, %d, %d, %s, %s, %d, %d, %s, %d, %s)"
. 'ON DUPLICATE KEY UPDATE
- cured = VALUES(`cured`),
+ cure_status = VALUES(`cure_status`),
+ is_restored = VALUES(`is_restored`),
last_cure_date = VALUES(`last_cure_date`),
fail_reason = VALUES(`fail_reason`),
scanner_start_local_date = VALUES(`scanner_start_local_date`),
@@ -199,7 +219,8 @@ public function logCureResult(CureLogRecord $cure_log_record)
$cure_log_record->full_hash,
$cure_log_record->cured_hash,
$cure_log_record->real_path,
- $cure_log_record->cured,
+ $cure_log_record->cure_status,
+ $cure_log_record->is_restored,
$cure_log_record->weak_spots_cured,
$cure_log_record->weak_spots_uncured,
$cure_log_record->cci_cured,
@@ -225,7 +246,7 @@ public static function parseWeakSpotsFromCureResult($weak_spots_result)
'signature_id' => isset($data['signature_id']) ? $data['signature_id'] : '',
'error' => isset($data['error']) ? $data['error'] : '',
);
- if (isset($data['cured']) && $data['cured'] === 1) {
+ if (isset($data['weakspot_is_cured']) && $data['weakspot_is_cured'] === 1) {
$cured[] = $result_row;
} else {
$uncured[] = $result_row;
@@ -241,4 +262,138 @@ public static function parseWeakSpotsFromCureResult($weak_spots_result)
}
return array('cured' => $cured, 'uncured' => $uncured);
}
+
+ /**
+ * @return array
+ */
+ public function getCuredFilesFastHashes()
+ {
+ $query = '
+ SELECT fast_hash FROM ' . SPBC_TBL_CURE_LOG . '
+ WHERE cure_status = 1;
+ ';
+ $result = $this->db->fetchAll($query);
+ if (is_null($result) || is_object($result)) {
+ $result = array();
+ }
+ return $result;
+ }
+
+ /**
+ * @param $fast_hashes_only
+ * @return array
+ */
+ public function getRestoredFiles($fast_hashes_only = false)
+ {
+ $query = '
+ SELECT ' . ($fast_hashes_only ? 'fast_hash' : '*') . ' FROM ' . SPBC_TBL_CURE_LOG . '
+ WHERE is_restored = 1;
+ ';
+ $result = $this->db->fetchAll($query);
+ if (is_null($result) || is_object($result)) {
+ $result = array();
+ }
+ return $result;
+ }
+
+ /**
+ * Check if there is failed cure tries
+ * @return bool
+ */
+ public function hasFailedCureTries()
+ {
+ // skip restored files!
+ $query = 'SELECT COUNT(*) as cnt FROM ' . SPBC_TBL_CURE_LOG . ' WHERE cure_status <> 1 AND is_restored <> 1';
+ $result = $this->db->fetch($query);
+ return (bool)$result->cnt;
+ }
+
+ /**
+ * Get totally failed files fast hashes. If nothing was cured at all.
+ * @return array
+ */
+ public function getTotallyFailedFilesFastHashes()
+ {
+ $query = 'SELECT fast_hash FROM ' . SPBC_TBL_CURE_LOG . ' WHERE cure_status = 0';
+ $result = $this->db->fetchAll($query);
+ if (is_null($result) || is_object($result)) {
+ $result = array();
+ }
+ return $result;
+ }
+
+ /**
+ * Delete a cure log record by fast hash
+ * @param $fast_hash
+ * @return void
+ */
+ public function deleteCureLogRecord($fast_hash)
+ {
+ $query = 'DELETE FROM ' . SPBC_TBL_CURE_LOG . ' WHERE fast_hash = %s';
+ $this->db->prepare($query, array($fast_hash))->execute();
+ }
+
+ /**
+ * Deletes cure log record if status is not cured but file has no signatures treatment
+ * @return void
+ */
+ public function removeIrrelevantFailedFiles()
+ {
+ $query = 'DELETE FROM ' . SPBC_TBL_CURE_LOG .
+ ' WHERE cure_status = 0 and fast_hash IN
+ (
+ SELECT fast_hash FROM ' . SPBC_TBL_SCAN_FILES . '
+ WHERE weak_spots IS NULL OR weak_spots NOT LIKE "%SIGNATURES%"
+ );';
+ $this->db->execute($query);
+ }
+
+ /**
+ * Remove irrelevant restored files from cure log.
+ * Deletes all the files that has current md5 differ from cured or full hash.
+ * @return void
+ */
+ public function removeIrrelevantRestoredFiles()
+ {
+ $restored_files = $this->getRestoredFiles();
+ if (empty($restored_files)) {
+ return;
+ }
+ $to_remove = array();
+ foreach ($restored_files as $restored_file) {
+ if (
+ !empty($restored_file['real_path']) &&
+ !empty($restored_file['fast_hash']) &&
+ !empty($restored_file['cured_hash']) &&
+ !empty($restored_file['full_hash'])
+ ) {
+ $current_md5 = @md5_file(spbc_get_root_path() . $restored_file['real_path']);
+ if ($current_md5 !== $restored_file['cured_hash'] && $current_md5 !== $restored_file['full_hash']) {
+ $to_remove[] = $restored_file['fast_hash'];
+ }
+ }
+ }
+ $this->db->execute(
+ 'DELETE FROM ' . SPBC_TBL_CURE_LOG . ' WHERE fast_hash IN ("' . implode('","', $to_remove) . '");'
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function getCureLogData()
+ {
+ // get cure log data
+ $query = '
+ SELECT fast_hash, full_hash, cured_hash, cure_status, last_cure_date, is_restored
+ FROM ' . SPBC_TBL_CURE_LOG . '
+ GROUP BY fast_hash;
+ ';
+ $result = $this->db->fetchAll($query, OBJECT_K);
+
+ if (is_null($result) || is_object($result)) {
+ $result = array();
+ }
+ return $result;
+ }
}
diff --git a/lib/CleantalkSP/SpbctWP/Scanner/CureLog/CureLogRecord.php b/lib/CleantalkSP/SpbctWP/Scanner/CureLog/CureLogRecord.php
index b9c69a9d..ddb200ba 100644
--- a/lib/CleantalkSP/SpbctWP/Scanner/CureLog/CureLogRecord.php
+++ b/lib/CleantalkSP/SpbctWP/Scanner/CureLog/CureLogRecord.php
@@ -26,7 +26,11 @@ class CureLogRecord extends DTO
/**
* @var int
*/
- public $cured = 0;
+ public $cure_status = 0;
+ /**
+ * @var int
+ */
+ public $is_restored = 0;
/**
* @var string
*/
@@ -66,7 +70,7 @@ class CureLogRecord extends DTO
'full_hash',
'cured_hash',
'real_path',
- 'cured',
+ 'cure_status',
'weak_spots_cured',
'weak_spots_uncured',
'cci_cured',
diff --git a/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php b/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php
index f14d2fcd..867e11c2 100755
--- a/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php
+++ b/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php
@@ -2,6 +2,7 @@
namespace CleantalkSP\SpbctWP\Scanner;
+use CleantalkSP\SpbctWP\Scanner\CureLog\CureLog;
use CleantalkSP\SpbctWP\Scanner\ScanningLog\ScanningLogFacade;
use CleantalkSP\SpbctWP\Scanner\ScanningStagesModule\ScannerFileStatuses;
use CleantalkSP\SpbctWP\Scanner\ScanningStagesModule\ScanningStagesStorage;
@@ -38,11 +39,11 @@ class ScannerQueue
*/
public static $stages = array(
'get_cms_hashes',
- 'get_modules_hashes',
+ //'get_modules_hashes',
'clean_results',
'file_system_analysis',
- 'get_denied_hashes',
- 'get_approved_hashes',
+ //'get_denied_hashes',
+ //'get_approved_hashes',
'signature_analysis',
'heuristic_analysis',
'schedule_send_heuristic_suspicious_files',
@@ -870,6 +871,16 @@ public function file_system_analysis($offset = null, $amount = null, $path_to_sc
. ' (`path`, `size`, `perms`, `mtime`, `fast_hash`, `full_hash`, `detected_at`, `checked_heuristic`) VALUES ';
foreach ( $scanner->output_files as $_key => $file ) {
+ // skip restored files as is
+ $cure_log = new CureLog();
+ $restored = $cure_log->getRestoredFiles();
+ if (!empty($restored)) {
+ foreach ($restored as $restored_file) {
+ if ($restored_file['real_path'] === $file['path']) {
+ continue 2;
+ }
+ }
+ }
$file['path'] = trim($this->db->prepare('%s', $file['path'])->getQuery(), '\'');
$file['detected_at'] = $detected_at;
@@ -1707,14 +1718,13 @@ public function auto_cure_backup() // phpcs:ignore PSR1.Methods.CamelCapsMethodN
public function auto_cure($offset = null, $amount = null) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
{
global $spbc;
- if ( $spbc->data['license_trial'] == 1 ) {
- $output = [
+ $auto_cure_enabled = isset($spbc->settings['scanner__auto_cure']) && $spbc->settings['scanner__auto_cure'] == 1;
+ if ( $spbc->data['license_trial'] == 1 || !$auto_cure_enabled) {
+ return [
'processed' => 0,
'cured' => 0,
'end' => 1
-
];
- return $output;
}
$amount = isset($amount) ? $amount : $this->amount;
diff --git a/lib/CleantalkSP/SpbctWP/Scanner/Stages/CureStage.php b/lib/CleantalkSP/SpbctWP/Scanner/Stages/CureStage.php
index c56e4eaa..a86b5e54 100644
--- a/lib/CleantalkSP/SpbctWP/Scanner/Stages/CureStage.php
+++ b/lib/CleantalkSP/SpbctWP/Scanner/Stages/CureStage.php
@@ -58,7 +58,8 @@ public function runStage($offset, $amount)
//count first offset counter for total file
//todo fix this (int) cast, if false - this is error
if ( $offset === 0 ) {
- //$cure_log->clearLogDataFromFailedCures();
+ $cure_log->removeIrrelevantRestoredFiles();
+ $cure_log->removeIrrelevantFailedFiles();
$this->total_files_to_cure_at_first_run = count($this->getFilesToCure());
//to facade log
$stage_data_obj->increase('count_files', $this->total_files_to_cure_at_first_run);
@@ -72,7 +73,7 @@ public function runStage($offset, $amount)
foreach ( $files as $file ) {
$cure_result = $this->processCure($file);
$cure_log->logCureResult($cure_result);
- if ( $cure_result->cured ) {
+ if ( $cure_result->cure_status === 1 ) {
//for logs sending way
$cured[$file['path']] = 'CURED';
}
@@ -102,6 +103,7 @@ public function runStage($offset, $amount)
*/
public function getFilesToCure($limit = null)
{
+ // get files with signatures
$files_with_signatures = '
SELECT fast_hash, full_hash, mtime
FROM ' . SPBC_TBL_SCAN_FILES . '
@@ -109,17 +111,26 @@ public function getFilesToCure($limit = null)
';
$files_with_signatures = $this->db->fetchAll($files_with_signatures, OBJECT_K);
- $cure_log_data = '
- SELECT fast_hash, full_hash, cured_hash, cured, last_cure_date
- FROM ' . SPBC_TBL_CURE_LOG . '
- GROUP BY fast_hash;
- ';
- $cure_log_data = $this->db->fetchAll($cure_log_data, OBJECT_K);
+ // get cure log data
+ $cure_log = new CureLog();
+ $cure_log_data = $cure_log->getCureLogData();
$to_cure_fast_hashes = array();
foreach ($files_with_signatures as $key => $value) {
if (isset($cure_log_data[$key])) { //fast hash found, do check for last cure date and hash
$found_by_fast_hash = $cure_log_data[$key];
+ // skip restored files
+ if ($found_by_fast_hash->is_restored == 1) {
+ continue;
+ }
+
+ // get files were not cured on this scan
+ $is_old_scan = (time() - (int)$found_by_fast_hash->last_cure_date) > 5;
+ if ((int)$found_by_fast_hash->cure_status == 0 && $is_old_scan) { // file was cured more than 5 secs ago
+ $to_cure_fast_hashes[] = $key;
+ continue;
+ }
+ // get files were cured but changed since last scan
if ((int)$found_by_fast_hash->last_cure_date < (int)$value->mtime) { // file was changed after last cure
if ($found_by_fast_hash->cured_hash !== $value->full_hash) { // file hash cured changed after last cure
$to_cure_fast_hashes[] = $key;
@@ -160,7 +171,8 @@ public function processCure($file)
'full_hash' => isset($file['full_hash']) ? $file['full_hash'] : '',
'cured_hash' => '',
'real_path' => isset($file['path']) ? $file['path'] : '',
- 'cured' => 0,
+ 'cure_status' => 0,
+ 'is_restored' => 0,
'weak_spots_cured' => '',
'weak_spots_uncured' => '',
'cci_cured' => null,
@@ -180,7 +192,7 @@ public function processCure($file)
//process Cure
$cure_file_result = $this->doCureFile($file);
if ( isset($cure_file_result->result['error']) ) {
- $cure_log_record->cured = 0;
+ $cure_log_record->cure_status = 0;
$cure_log_record->fail_reason = $cure_file_result->result['error'];
return $cure_log_record;
}
@@ -197,7 +209,7 @@ public function processCure($file)
);
//if cured, rescan file with heuristic
- if ( $cure_log_record->cured !== 0 ) {
+ if ( $cure_log_record->cure_status !== 0 ) {
$recheck_result = $this->rescanFileHeuristic($file);
$cure_log_record->heuristic_rescan_result = json_encode($recheck_result);
//if rescanned, update results table
@@ -224,7 +236,7 @@ private function preCheckFile($file, $cure_log_record)
//check if file has backup
if ( !$this->fileHasBackup($file) ) {
//cure is not safe without backups, log this and return cure_log_record
- $cure_log_record->cured = 0;
+ $cure_log_record->cure_status = 0;
$cure_log_record->fail_reason = __('File has no backup.', "security-malware-firewall");
return $cure_log_record;
} else {
@@ -275,12 +287,14 @@ private function updateScanResultsTableOnAfterCure($file, $cure_log_record, $wea
if ( !empty($log_uncured) && !empty($log_cured) ) {
//if Cure process errored keep the reason
$cure_log_record->fail_reason = __('Partially success, has uncured weak spots.', 'security-malware-firewall');
- $cure_log_record->cured = -1;
+ $cure_log_record->cure_status = -1;
+ $cure_log_record->cci_cured = count($log_cured);
} else if ( empty($log_uncured) && !empty($log_cured) ) {
- $cure_log_record->cured = 1;
+ $cure_log_record->cure_status = 1;
+ $cure_log_record->cci_cured = count($log_cured);
} else {
$cure_log_record->fail_reason = __('Has uncured weak spots.', 'security-malware-firewall');
- $cure_log_record->cured = 0;
+ $cure_log_record->cure_status = 0;
}
$weak_spots_lines_to_remove = array_map(
@@ -447,20 +461,4 @@ public function getStageResult()
{
return $this->stage_result;
}
-
- /**
- * @return array
- */
- public function getCuredFilesFastHashes()
- {
- $query = '
- SELECT fast_hash FROM ' . SPBC_TBL_CURE_LOG . '
- WHERE cured = 1;
- ';
- $result = $this->db->fetchAll($query);
- if (is_null($result) || is_object($result)) {
- $result = array();
- }
- return $result;
- }
}