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 6f8c17227..1538307c9 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 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 + '
' + 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 let action = self.siblings('select').children()[self.siblings('select').first()[0].selectedIndex].value;\n if (!spbcBulkAction && !noConfirmActions.any.includes(action) && !confirm(spbcTable.warning_bulk)) {\n return;\n }\n\n spbcBulkAction = self;\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 = '
';\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 let selectedItems = current.closest('#spbc_tbl__scanner_cure_log').find(selector);\n\n if (selectedItems.length === 0) {\n selectedItems = current.closest('#spbc_scan_accordion_tab_critical').find(selector);\n }\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
+{"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 let action = self.siblings('select').children()[self.siblings('select').first()[0].selectedIndex].value;\n if (!spbcBulkAction && !noConfirmActions.any.includes(action) && !confirm(spbcTable.warning_bulk)) {\n return;\n }\n\n spbcBulkAction = self;\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 let selectedItems = current.closest('#spbc_tbl__scanner_cure_log').find(selector);\n\n if (selectedItems.length === 0) {\n selectedItems = current.closest('#spbc_scan_accordion_tab_critical').find(selector);\n }\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.prompt(\n 'Copy the file info below and send it to ' + spbcSettings['wl_support_email'],\n result.data.file_info,\n );\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-admin.js b/js/src/spbc-admin.js
index 0f967bf8a..a315224e8 100644
--- a/js/src/spbc-admin.js
+++ b/js/src/spbc-admin.js
@@ -299,11 +299,30 @@ jQuery(document).ready(function() {
});
if (spbcSettings['wl_mode_enabled']) {
+ // any usage of non WL name
jQuery('.plugin-title strong').each( function(i, item) {
if (jQuery(item).html().indexOf('Security by CleanTalk') >= 0) {
jQuery(item).html(jQuery(item).html().replace('CleanTalk', spbcSettings['wl_company_name']));
}
});
+ // Edit plugin update chunks and links
+ const updateLink = jQuery(
+ '.plugin-update-tr[data-slug="security-malware-firewall"] .open-plugin-details-modal',
+ );
+ const updateText = updateLink.text();
+ const version = updateText.match(/version (\d+\.\d+)/i)?.[1];
+ updateLink.remove();
+ jQuery('.plugin-update-tr[data-slug="security-malware-firewall"] p').each(function() {
+ let href = jQuery(
+ `.plugin-update-tr[data-slug="security-malware-firewall"]
+ a[aria-label="Update Security by CleanTalk now"]`,
+ );
+ const textToReplace = 'Update now to ' + version;
+ href.text(textToReplace);
+ jQuery(this).text(jQuery(this).text().replace(' or ', ''));
+ jQuery(this).text(jQuery(this).text().replace(textToReplace + '.', ' '));
+ jQuery(this).append(href);
+ });
}
});
diff --git a/js/src/spbc-table.js b/js/src/spbc-table.js
index 709011cf9..71ecf4919 100644
--- a/js/src/spbc-table.js
+++ b/js/src/spbc-table.js
@@ -551,8 +551,10 @@ function spbcTblRowActionsCallback(result, data, params, obj) {
data.add_action === 'copy_file_info'
) {
if (result.success === true && result.data.file_info) {
- window.
- prompt('Copy the file info below and send it to support@cleantalk.org: ', result.data.file_info);
+ window.prompt(
+ 'Copy the file info below and send it to ' + spbcSettings['wl_support_email'],
+ result.data.file_info,
+ );
} else {
let errorText = (typeof result.data.error !== 'undefined') ?
result.data.error :
diff --git a/lib/CleantalkSP/Common/HTTP/Request.php b/lib/CleantalkSP/Common/HTTP/Request.php
index 0271d47d1..892ccbde0 100644
--- a/lib/CleantalkSP/Common/HTTP/Request.php
+++ b/lib/CleantalkSP/Common/HTTP/Request.php
@@ -417,7 +417,7 @@ protected function appendOptionsObligatory()
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 5000,
CURLOPT_FORBID_REUSE => true,
- CURLOPT_USERAGENT => self::AGENT . '; ' . (Server::get('SERVER_NAME') ?: 'UNKNOWN_HOST'),
+ CURLOPT_USERAGENT => self::AGENT . '; ' . (Server::getString('SERVER_NAME') ?: 'UNKNOWN_HOST'),
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $this->data,
CURLOPT_SSL_VERIFYPEER => false,
diff --git a/lib/CleantalkSP/Common/Helpers/IP.php b/lib/CleantalkSP/Common/Helpers/IP.php
index eac7edb69..25369818e 100644
--- a/lib/CleantalkSP/Common/Helpers/IP.php
+++ b/lib/CleantalkSP/Common/Helpers/IP.php
@@ -174,9 +174,9 @@ public static function get($ip_type_to_get = 'real', $headers = array(), $recurs
break;
// Remote addr
case 'remote_addr':
- $ip_version = self::validate(Server::get('REMOTE_ADDR'));
+ $ip_version = self::validate(Server::getString('REMOTE_ADDR'));
if ($ip_version) {
- $out = $ip_version === 'v6' ? self::normalizeIPv6(Server::get('REMOTE_ADDR')) : Server::get('REMOTE_ADDR');
+ $out = $ip_version === 'v6' ? self::normalizeIPv6(Server::getString('REMOTE_ADDR')) : Server::getString('REMOTE_ADDR');
}
break;
// X-Forwarded-For
@@ -237,7 +237,7 @@ public static function get($ip_type_to_get = 'real', $headers = array(), $recurs
self::isIPInPrivateNetworks($out, $ip_version) ||
self::isIPInNetwork(
$out,
- Server::get('SERVER_ADDR') . '/24',
+ Server::getString('SERVER_ADDR') . '/24',
$ip_version
)
))
diff --git a/lib/CleantalkSP/Common/RemoteCalls.php b/lib/CleantalkSP/Common/RemoteCalls.php
index ccda28f37..e0724c5bb 100644
--- a/lib/CleantalkSP/Common/RemoteCalls.php
+++ b/lib/CleantalkSP/Common/RemoteCalls.php
@@ -41,16 +41,16 @@ class RemoteCalls
*/
public static function check()
{
- return Request::get('spbc_remote_call_token')
+ return Request::getString('spbc_remote_call_token')
? self::checkWithToken()
: self::checkWithoutToken();
}
public static function checkWithToken()
{
- return Request::get('spbc_remote_call_token') &&
- Request::get('spbc_remote_call_action') &&
- in_array(Request::get('plugin_name'), array('security', 'spbc'));
+ return Request::getString('spbc_remote_call_token') &&
+ Request::getString('spbc_remote_call_action') &&
+ in_array(Request::getString('plugin_name'), array('security', 'spbc'));
}
public static function checkWithoutToken()
@@ -63,8 +63,8 @@ public static function checkWithoutToken()
];
return ! $spbc->key_is_ok &&
- Request::get('spbc_remote_call_action') &&
- in_array(Request::get('plugin_name'), array('security', 'spbc')) &&
+ Request::getString('spbc_remote_call_action') &&
+ in_array(Request::getString('plugin_name'), array('security', 'spbc')) &&
in_array(IP::resolve(IP::get('remote_addr')), $rc_servers, true);
}
@@ -80,8 +80,8 @@ private static function isAllowedWithoutToken($rc)
*/
public function process()
{
- $action = strtolower(Request::get('spbc_remote_call_action'));
- $token = strtolower(Request::get('spbc_remote_call_token'));
+ $action = strtolower(Request::getString('spbc_remote_call_action'));
+ $token = strtolower(Request::getString('spbc_remote_call_token'));
$method = 'action__' . $action;
if (isset($this->state->remote_calls[$action])) {
@@ -90,7 +90,7 @@ public function process()
: self::COOLDOWN;
// Return OK for test remote calls
- if (Request::get('test')) {
+ if (Request::getString('test')) {
die('OK');
}
diff --git a/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/HeuristicAnalyser.php b/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/HeuristicAnalyser.php
index 7b918c4ed..c7c2b2398 100644
--- a/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/HeuristicAnalyser.php
+++ b/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/HeuristicAnalyser.php
@@ -33,6 +33,10 @@ class HeuristicAnalyser
{
// Constants
const HEURISTIC_SCAN_MAX_FILE_SIZE = 524288; // 512 KB
+ /**
+ * Maximum number of keys to return in the entropy verdict. This is to prevent the verdict from being too large.
+ */
+ const HEURISTIC_MAX_ENTROPY_VERDICT_KEYS = 10;
// Current file attributes
/**
@@ -234,10 +238,10 @@ public function __construct($input, $self = null)
$currentMemoryLimitBytes = $this->convertToBytes($currentMemoryLimit);
$compareValueBytes = $this->convertToBytes('256M');
- if ($currentMemoryLimitBytes >= $compareValueBytes) {
+ if ($currentMemoryLimit === '-1' || $currentMemoryLimitBytes >= $compareValueBytes) {
if ( isset($input['path']) && version_compare(PHP_VERSION, '8.1', '>=') && extension_loaded('mbstring') ) {
// Do not run entropy analysis on included constructs
- $this->entropyAnalyser = new Entropy($input['path']);
+ $this->entropyAnalyser = new Entropy($input['path'], $this->tokens);
}
}
}
@@ -434,7 +438,7 @@ public function processContent()
// Detecting bad variables
$this->variables->detectBad();
if ( $this->entropyAnalyser ) {
- $this->entropyAnalyser->analyse($this->variables);
+ $this->entropyAnalyser->extractSuspiciousVariables($this->variables);
}
/** Gather the results of scanning */
@@ -549,8 +553,12 @@ public function makeVerdict()
}
}
- if ( $this->entropyAnalyser && $this->entropyAnalyser->getVerdict() ) {
- $this->verdict['SUSPICIOUS'] = $this->entropyAnalyser->getVerdict();
+ $entropy_verdict_final = $this->entropyAnalyser ?
+ $this->entropyAnalyser->getEntropyVerdict(static::HEURISTIC_MAX_ENTROPY_VERDICT_KEYS) :
+ null;
+
+ if ( $entropy_verdict_final ) {
+ $this->verdict['SUSPICIOUS'] = $entropy_verdict_final;
}
// Detecting JavaScript injection in HTML
diff --git a/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/Entropy.php b/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/Entropy.php
index e3b7b7acb..6fe7899fa 100644
--- a/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/Entropy.php
+++ b/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/Entropy.php
@@ -6,23 +6,96 @@
class Entropy
{
+ /**
+ * Min length of variable to be suspicious
+ */
+ const SUSPICIOUS_VARIABLES_MIN_LENGTH = 3;
+ /**
+ * Threshold for variable tokenization, less is suspicious
+ */
+ const SUSPICIOUS_VARIABLES_THRESHOLD = 2;
+ /**
+ * Min length of array key to be suspicious
+ */
+ const SUSPICIOUS_ARRAY_KEYS_ENTROPY__MIN_KEY_LENGTH = 3;
+ /**
+ * Threshold for array keys tokenization, less is suspicious. Increment this to force sensitivity.
+ */
+ const SUSPICIOUS_ARRAY_KEYS_ENTROPY__THRESHOLD = 2.5;
+ /**
+ * How to reduce a single array key tokenization before check to show in the verdict. Increment this to force sensitivity.
+ */
+ const SUSPICIOUS_ARRAY_KEYS_ENTROPY__VERDICT_SHOWN_MULTIPLIER = 0.5;
+ /**
+ * MIn length of int key to be suspicious
+ */
+ const SUSPICIOUS_ARRAY_KEYS_LONGINT__MIN_KEY_LENGTH = 4;
+ /**
+ * Threshold for long int keys in array, more is suspicious
+ */
+ const SUSPICIOUS_ARRAY_KEYS_LONGINT__THRESHOLD = 0.3;
+
+ const SUSPICIOUS_ARRAY_KEYS_LONGINT_MIN__COUNT_OF_SUSPICIOUS = 5;
+
+ /**
+ * Verdict name of long integer in array key
+ */
+ const ENTROPY_VERDICT_ARRAY_KEYS_LONGINT_NAME = 'Long integer in array key';
+ /**
+ * Verdict name of high entropy in array key
+ */
+ const ENTROPY_VERDICT_ARRAY_KEYS_HIGH_ENTROPY_NAME = 'High entropy in array key';
+ /**
+ * Verdict name of high entropy in variable
+ */
+ const ENTROPY_VERDICT_VARIABLES_HIGH_ENTROPY_NAME = 'High entropy in variable name';
/**
* @var array|null
*/
- private $verdict;
+ private $entropy_verdict;
/**
* Flag - is need to check variables separately
* @var bool
*/
private $is_file_suspicious;
+ /**
+ * @var bool
+ */
+ private $has_suspicious_variables;
+ /**
+ * @var array
+ */
+ private $suspicious_array_calls = [];
/**
- * @param string $path
+ * Path to the file
+ * @var string
*/
- public function __construct($path)
+ private $path_to_file;
+
+ /**
+ * Filtered content with no comments, whitespaces. Used to find suspicious array keys.
+ * @var string
+ */
+ private $filtered_content;
+
+ /**
+ * @param string $path_to_file
+ * @param Tokens $tokens
+ */
+ public function __construct($path_to_file, $tokens)
{
- $this->is_file_suspicious = $this->analyseFile($path);
+ $this->path_to_file = $path_to_file;
+ // do filter content
+ $simplifier = new Simplifier($tokens);
+ foreach ($tokens as $token) {
+ $simplifier->deleteNonCodeTokens($token);
+ $simplifier->stripWhitespaces($token);
+ }
+ $this->filtered_content = $tokens->glueAllTokens();
+ //process
+ $this->is_file_suspicious = $this->analyseFile();
}
/**
@@ -31,63 +104,88 @@ public function __construct($path)
* @param Variables $variables
* @return void
*/
- public function analyse(Variables $variables)
+ public function extractSuspiciousVariables(Variables $variables)
{
if ( !$this->is_file_suspicious ) {
return;
}
- $variables_obj = $variables->variables;
- $variable_names = array_keys($variables->variables);
+ $encoder = new Encoder();
- if ( !count($variable_names) ) {
- return;
- }
+ if ( $this->has_suspicious_variables ) {
+ $variables_obj = $variables->variables;
+ $variable_names = array_keys($variables->variables);
- $encoder = new Encoder();
- $detected_unreadable_variables = [];
- foreach ( $variable_names as $variable ) {
- // do not change empty state! this change is from heur package!
- if ( empty($variables_obj[$variable]) ) {
- continue;
+ if ( !count($variable_names) ) {
+ return;
}
- if ( strpos($variable, '_') === 0 || strlen($variable) < 5 ) {
- continue;
- }
- $num_tokens = count($encoder->encode($variable));
- if ( ! $num_tokens ) {
- continue;
+
+ $detected_unreadable_variables = [];
+ foreach ( $variable_names as $variable ) {
+ // do not change empty state! this change is from heur package!
+ if ( empty($variables_obj[$variable]) ) {
+ continue;
+ }
+ if ( strpos($variable, '_') === 0 || strlen($variable) < 5 ) {
+ continue;
+ }
+ $num_tokens = count($encoder->encode($variable));
+ if ( ! $num_tokens ) {
+ continue;
+ }
+ $res = strlen($variable) / $num_tokens;
+ $line_number_met_on = isset($variables_obj[$variable][0][2]) && is_scalar($variables_obj[$variable][0][2])
+ ? (int)$variables_obj[$variable][0][2]
+ : null;
+ if ( $res < static::SUSPICIOUS_VARIABLES_THRESHOLD && null !== $line_number_met_on ) {
+ $detected_unreadable_variables[$line_number_met_on] = [static::ENTROPY_VERDICT_VARIABLES_HIGH_ENTROPY_NAME];
+ }
}
- $res = strlen($variable) / $num_tokens;
- if ( $res < 2 && isset($variables_obj[$variable][0][2]) ) {
- $detected_unreadable_variables[$variables_obj[$variable][0][2]] = [$variable];
+
+ if ( count($detected_unreadable_variables) ) {
+ $this->entropy_verdict = $detected_unreadable_variables;
}
}
- if ( count($detected_unreadable_variables) ) {
- $this->verdict = $detected_unreadable_variables;
+ if ( empty($this->entropy_verdict) && !empty($this->suspicious_array_calls)) {
+ $this->entropy_verdict = $this->suspicious_array_calls;
}
}
/**
* Analysing average unreadable score for the full file
*
- * @param $path
* @return bool
*/
- private function analyseFile($path)
+ private function analyseFile()
{
- $variable_names = $this->extractVariableNames($path);
+ $this->has_suspicious_variables = $this->analyseVariableCalls();
+ if ( !$this->has_suspicious_variables ) {
+ $this->suspicious_array_calls = $this->analyseArrayKeyCalls();
+ }
+ return $this->has_suspicious_variables || !empty($this->suspicious_array_calls);
+ }
+
+ /**
+ * Analysing average unreadable variable score for the full file
+ *
+ *
+ * @return bool
+ */
+ private function analyseVariableCalls()
+ {
+ $variable_names = $this->extractVariableNames();
$filtered_names = [];
+
foreach ( $variable_names as $variable_name ) {
- if ( strpos($variable_name, '_') !== 0 && strlen($variable_name) >= 5 ) {
+ if ( strpos($variable_name, '_') !== 0 && strlen($variable_name) >= static::SUSPICIOUS_VARIABLES_MIN_LENGTH ) {
$filtered_names[] = $variable_name;
}
}
$filtered_names = array_unique($filtered_names);
- if ( count($filtered_names) > 3 ) {
+ if ( count($filtered_names) > static::SUSPICIOUS_VARIABLES_MIN_LENGTH ) {
$encoder = new Encoder();
$sum = 0;
@@ -102,7 +200,7 @@ private function analyseFile($path)
$average_tokenization = $sum / count($filtered_names);
- if ( $average_tokenization < 2 ) {
+ if ( $average_tokenization < static::SUSPICIOUS_VARIABLES_THRESHOLD ) {
return true;
}
}
@@ -110,21 +208,244 @@ private function analyseFile($path)
}
/**
- * @param $path
+ * Analysing average unreadable variable score for the full file
+ *
+ * @return array
+ */
+ private function analyseArrayKeyCalls()
+ {
+ //perform entropy analysis for array keys
+ $suspicious_calls = $this->analyzeArrayKeysEntropy();
+
+ if (empty($suspicious_calls)) {
+ //if nothing found perform long int count analysis
+ $suspicious_calls = $this->analyzeArrayKeysLongInt();
+ }
+
+ return $suspicious_calls;
+ }
+
+ /**
+ * Analysing average unreadable array keys score for the full file
+ *
+ * @return array
+ */
+ private function analyzeArrayKeysEntropy()
+ {
+ $output = [];
+ $array_keys_calls = $this->extractArrayKeysWordLike();
+ $filtered_keys = [];
+
+ foreach ( $array_keys_calls as $key ) {
+ if ( strlen($key) >= static::SUSPICIOUS_ARRAY_KEYS_ENTROPY__MIN_KEY_LENGTH ) {
+ $filtered_keys[] = $key;
+ }
+ }
+
+ $filtered_keys = array_unique($filtered_keys);
+ if ( count($filtered_keys) > 3 ) {
+ $encoder = new Encoder();
+ $sum = 0;
+
+ foreach ( $filtered_keys as $key ) {
+ $num_tokens = count($encoder->encode($key));
+ if ( ! $num_tokens ) {
+ continue;
+ }
+ $res = strlen($key) / $num_tokens;
+ $sum += $res;
+ }
+
+ $average_array_key_tokenization = $sum / count($filtered_keys);
+ if ( (float)$average_array_key_tokenization < static::SUSPICIOUS_ARRAY_KEYS_ENTROPY__THRESHOLD ) {
+ foreach ( $filtered_keys as $key ) {
+ $num_tokens = count($encoder->encode($key));
+ if ( ! $num_tokens ) {
+ continue;
+ }
+ $res = strlen($key) / $num_tokens;
+ if ( (float)$res < static::SUSPICIOUS_ARRAY_KEYS_ENTROPY__THRESHOLD * static::SUSPICIOUS_ARRAY_KEYS_ENTROPY__VERDICT_SHOWN_MULTIPLIER ) {
+ $found_on_lines = static::findRowsNumWithPattern($this->path_to_file, '/\[\'' . $key . '\'\]/');
+ foreach ( $found_on_lines as $line_num ) {
+ $output[$line_num] = [static::ENTROPY_VERDICT_ARRAY_KEYS_HIGH_ENTROPY_NAME];
+ }
+ }
+ }
+ }
+ }
+ return $output;
+ }
+
+ /**
+ * Analysing average long int in array call score for the full file
+ *
+ * @return array
+ */
+ private function analyzeArrayKeysLongInt()
+ {
+ $output = [];
+ $array_keys_int = $this->extractArrayKeysIntLike();
+ $total_int_keys_calls = count($array_keys_int);
+ $probably_long_int = [];
+ foreach ($array_keys_int as $int) {
+ if (strlen($int) >= static::SUSPICIOUS_ARRAY_KEYS_LONGINT__MIN_KEY_LENGTH) {
+ $found_on_lines = static::findRowsNumWithPattern($this->path_to_file, '/\[' . $int . '\]/');
+ foreach ($found_on_lines as $line_num) {
+ $probably_long_int[$line_num] = [static::ENTROPY_VERDICT_ARRAY_KEYS_LONGINT_NAME];
+ }
+ }
+ }
+ if (
+ count($probably_long_int) >= static::SUSPICIOUS_ARRAY_KEYS_LONGINT_MIN__COUNT_OF_SUSPICIOUS &&
+ (float)($total_int_keys_calls / count($probably_long_int)) > static::SUSPICIOUS_ARRAY_KEYS_LONGINT__THRESHOLD
+ ) {
+ $output = $probably_long_int;
+ }
+ return $output;
+ }
+
+ /**
+ * Extract variable names from the file
+ * @return string[]
+ */
+ private function extractVariableNames()
+ {
+ $pattern = '/\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)/';
+ return static::extractContentByRegexp($this->filtered_content, $pattern);
+ }
+
+ /**
+ * Extract int-like array keys from the file
+ * @return string[]
+ */
+ private function extractArrayKeysWordLike()
+ {
+ $pattern = '/\[\'([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\'\]/';
+ return static::extractContentByRegexp($this->filtered_content, $pattern);
+ }
+
+ /**
+ * Extract word-like array keys from the file
* @return string[]
*/
- private function extractVariableNames($path)
+ private function extractArrayKeysIntLike()
{
- $content = file_get_contents($path);
- preg_match_all('/\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)/', $content, $matches);
- return $matches[1];
+ $pattern = '/\[(\d+)]/';
+ return static::extractContentByRegexp($this->filtered_content, $pattern);
+ }
+
+ /**
+ * @param string $content
+ * @param $pattern
+ *
+ * @return array|string[]
+ */
+ private static function extractContentByRegexp($content, $pattern)
+ {
+ preg_match_all($pattern, $content, $matches);
+ return isset($matches[1]) ? $matches[1] : [];
+ }
+
+ /**
+ * Find each row in a file that matches a specified regular expression.
+ *
+ * @param string $filePath The path to the file.
+ * @param string $pattern The regular expression pattern to search for.
+ * @return array An array of lines that match the regular expression.
+ */
+ private static function findRowsNumWithPattern($filePath, $pattern)
+ {
+ $result = [];
+ if (!class_exists('\SplFileObject')) {
+ return array();
+ }
+ $file = new \SplFileObject($filePath);
+ $line_num = 0;
+
+ while (!$file->eof()) {
+ $line_num++;
+ $line = $file->fgets();
+ if (preg_match($pattern, $line)) {
+ $result[] = $line_num;
+ }
+ }
+
+ return $result;
}
/**
* @return array|null
*/
- public function getVerdict()
+ public function getEntropyVerdict($max_keys_number = 0)
{
- return $this->verdict;
+ if (
+ $max_keys_number !== 0
+ && is_array($this->entropy_verdict)
+ && count($this->entropy_verdict) > $max_keys_number
+ ) {
+ return static::reduceVerdict($this->entropy_verdict, $max_keys_number);
+ }
+ return $this->entropy_verdict;
+ }
+
+ /**
+ * Reduce verdict to max keys number
+ * @param $verdict
+ * @param $max_keys
+ *
+ * @return array
+ */
+ private static function reduceVerdict($verdict, $max_keys)
+ {
+ $verdict_of_array_checks = [];
+ $verdict_other = [];
+ // we need to separate array checks from other checks
+ foreach ($verdict as $line => $value) {
+ if (is_array($value)) {
+ if (
+ $value[0] === static::ENTROPY_VERDICT_ARRAY_KEYS_HIGH_ENTROPY_NAME ||
+ $value[0] === static::ENTROPY_VERDICT_ARRAY_KEYS_LONGINT_NAME
+ ) {
+ $verdict_of_array_checks[$line] = $value;
+ } else {
+ $verdict_other[$line] = $value;
+ }
+ }
+ }
+ if (count($verdict_other) + count($verdict_of_array_checks) !== count($verdict)) {
+ throw new \RuntimeException('Verdict reduction error');
+ }
+ //first, if we have found array checks - reduce them
+ if (count($verdict_of_array_checks) > 2 && count($verdict_other) <= $max_keys) {
+ $verdict_of_array_checks = static::halfVerdictArray($verdict_of_array_checks, $max_keys - count($verdict_other));
+ return count($verdict_other) // if other checks found - merge them
+ ? array_merge($verdict_other, $verdict_of_array_checks)
+ : $verdict_of_array_checks;
+ }
+ //if we have no array checks - reduce other checks by limit
+ return array_slice($verdict, 0, $max_keys, true);
+ }
+
+ /**
+ * Reduce verdict to max keys number deleting every second key.
+ * @param $array
+ * @param $max_keys
+ *
+ * @return array
+ */
+ private static function halfVerdictArray($array, $max_keys)
+ {
+ $counter = 3; //save first elem always
+ $halfed = [];
+ foreach ($array as $index => $value) {
+ $counter++;
+ if ($counter % 2 == 1) {
+ $halfed[$index] = $value;
+ }
+ }
+ unset($array);
+ return count($halfed) > $max_keys
+ ? static::halfVerdictArray($halfed, $max_keys)
+ : $halfed;
}
}
diff --git a/lib/CleantalkSP/Common/TT.php b/lib/CleantalkSP/Common/TT.php
new file mode 100644
index 000000000..2176fe35b
--- /dev/null
+++ b/lib/CleantalkSP/Common/TT.php
@@ -0,0 +1,194 @@
+getArrayCopy();
+ }
+ return (array)$value;
+ }
+ return $default !== array() && is_array($default) ? $default : array();
+ }
+
+ /**
+ * Converts a given value to a boolean.
+ *
+ * This method attempts to convert a given value to a boolean. It first checks if the value is already a boolean,
+ * in which case it returns the value as is. If the value is not a boolean, it attempts to cast the value to a boolean.
+ * This casting is useful for ensuring that the value can be worked with as a boolean, regardless of its original type.
+ * If the value is null or cannot be converted, false is returned.
+ *
+ * @param mixed $value The value to be converted to a boolean.
+ * @param bool $default Default value if conversion is not possible, inherit false.
+ * @return bool The converted boolean value, or false if conversion is not possible.
+ * @psalm-suppress UnusedMethod
+ */
+ public static function toBool($value, $default = false)
+ {
+ if ( isset($value) && is_bool($value) ) {
+ return $value;
+ }
+ if ( isset($value) && !is_bool($value) ) {
+ //todo cast methods needs
+ return (bool)$value;
+ }
+ return $default !== false && is_bool($default);
+ }
+
+ /**
+ * Retrieves a value from an array by key and converts it to an integer.
+ *
+ * This method looks for a specified key in an array and returns its value converted to an integer.
+ * If the key does not exist in the array, or the array itself is invalid, a default value is returned instead.
+ * The conversion to integer is handled by the `toInt` method, ensuring consistent type casting across the class.
+ *
+ * @param mixed $array The array from which to retrieve the value.
+ * @param int|string $key The key of the value to retrieve from the array.
+ * @param int $default The default value to return if the key is not found or the array is invalid. Defaults to 0.
+ * @return int The value retrieved from the array and converted to an integer, or the default value if not found.
+ * @psalm-suppress UnusedMethod
+ */
+ public static function getArrayValueAsInt($array, $key, $default = 0)
+ {
+ if ( !is_array($array) || !isset($array[$key]) ) {
+ return self::toInt($default);
+ }
+
+ return self::toInt($array[$key], $default);
+ }
+
+ /**
+ * Retrieves a value from an array by key and converts it to a string.
+ *
+ * This method looks for a specified key in an array and returns its value converted to a string.
+ * If the key does not exist in the array, or the array itself is invalid, a default value is returned instead.
+ * The conversion to string is handled by the `toString` method, ensuring consistent type casting across the class.
+ * @param mixed $array
+ * @param int|string $key
+ * @param string $default
+ * @return string
+ * @psalm-suppress UnusedMethod
+ */
+ public static function getArrayValueAsString($array, $key, $default = '')
+ {
+ if ( !is_array($array) || !isset($array[$key]) ) {
+ return self::toString($default);
+ }
+
+ return self::toString($array[$key], $default);
+ }
+
+ /**
+ * Retrieves a value from an array by key and converts it to an array.
+ *
+ * This method looks for a specified key in an array and returns its value converted to an array.
+ * If the key does not exist in the array, or the array itself is invalid, a default value is returned instead.
+ * The conversion to string is handled by the `toArray` method, ensuring consistent type casting across the class.
+ * @param mixed $array
+ * @param int|string $key
+ * @param array $default
+ * @return array
+ * @psalm-suppress UnusedMethod
+ */
+ public static function getArrayValueAsArray($array, $key, $default = array())
+ {
+ if ( !is_array($array) || !isset($array[$key]) ) {
+ return self::toArray($default);
+ }
+
+ return self::toArray($array[$key], $default);
+ }
+
+ /**
+ * Retrieves a value from an array by key and converts it to boolean.
+ * *
+ * * This method looks for a specified key in an array and returns its value converted to boolean.
+ * * If the key does not exist in the array, or the array itself is invalid, a default value is returned instead.
+ * * The conversion to string is handled by the `toBool` method, ensuring consistent type casting across the class.
+ * @param mixed $array
+ * @param int|string $key
+ * @param bool $default
+ * @return bool
+ * @psalm-suppress UnusedMethod
+ */
+ public static function getArrayValueAsBool($array, $key, $default = false)
+ {
+ if ( !is_array($array) || !isset($array[$key]) ) {
+ return self::toBool($default);
+ }
+
+ return self::toBool($array[$key], $default);
+ }
+}
diff --git a/lib/CleantalkSP/Fpdf/Pdf.php b/lib/CleantalkSP/Fpdf/Pdf.php
index e3e837870..d73370e45 100755
--- a/lib/CleantalkSP/Fpdf/Pdf.php
+++ b/lib/CleantalkSP/Fpdf/Pdf.php
@@ -18,10 +18,13 @@ class Pdf extends Fpdf
*/
public function Header() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
{
+ global $spbc;
$this->SetTextColor(150, 150, 150);
$this->setDocTextHeaders();
// Logo
- $this->Image(__DIR__ . DIRECTORY_SEPARATOR . 'img' . DIRECTORY_SEPARATOR . 'logo.png', 10, 6, 15);
+ if (!$spbc->data['wl_mode_enabled']) {
+ $this->Image(__DIR__ . DIRECTORY_SEPARATOR . 'img' . DIRECTORY_SEPARATOR . 'logo.png', 10, 6, 15);
+ }
$this->SetFont('Times', 'B', 15);
diff --git a/lib/CleantalkSP/Monitoring/User.php b/lib/CleantalkSP/Monitoring/User.php
index fbd463fcf..39e6dcc3d 100644
--- a/lib/CleantalkSP/Monitoring/User.php
+++ b/lib/CleantalkSP/Monitoring/User.php
@@ -20,12 +20,12 @@ public static function record()
$user_id = $current_user->ID;
$user_login = $current_user->user_login;
$last_activity = time();
- $page = substr(Server::get('REQUEST_URI'), 0, 500);
+ $page = substr(Server::getString('REQUEST_URI'), 0, 500);
$ip = IP::get();
$role = isset($current_user->roles[0])
? $current_user->roles[0]
: null;
- $user_agent = substr(strip_tags(Server::get('HTTP_USER_AGENT')), 0, 1000);
+ $user_agent = substr(strip_tags(Server::getString('HTTP_USER_AGENT')), 0, 1000);
// Inserting / updating user
$wpdb->replace(
diff --git a/lib/CleantalkSP/Security/Firewall.php b/lib/CleantalkSP/Security/Firewall.php
index f2e1e4155..eb12c3029 100644
--- a/lib/CleantalkSP/Security/Firewall.php
+++ b/lib/CleantalkSP/Security/Firewall.php
@@ -65,7 +65,7 @@ class Firewall
*/
public function __construct($db = null)
{
- $this->debug = (bool)Get::get('debug');
+ $this->debug = Get::getBool('debug');
$this->ip_array = $this->ipGet('real');
if ( isset($db) ) {
@@ -125,7 +125,7 @@ public function run()
if ($module->test_ip && $result->ip === $module->test_ip) {
$this->test_block = $result;
}
- if (Get::get('spbct_test_waf') && $result->module === 'WAF') {
+ if (Get::getString('spbct_test_waf') && $result->module === 'WAF') {
$this->test_block = $result;
}
}
diff --git a/lib/CleantalkSP/Security/RenameLoginPage.php b/lib/CleantalkSP/Security/RenameLoginPage.php
index dca45a80a..115ae82d8 100644
--- a/lib/CleantalkSP/Security/RenameLoginPage.php
+++ b/lib/CleantalkSP/Security/RenameLoginPage.php
@@ -42,7 +42,7 @@ public function __construct($login_slug, $redirect_slug)
$this->login_slug = $login_slug;
$this->redirect_slug = $redirect_slug;
- $this->request = parse_url(Server::get('REQUEST_URI')) ?: array();
+ $this->request = parse_url(Server::get('REQUEST_URI', null, 'url')) ?: array();
$this->request['path'] = isset($this->request['path']) ? $this->request['path'] : '';
}
}
diff --git a/lib/CleantalkSP/SpbctWP/AdminBannersModule/AdminBanners/AdminBannerTrial.php b/lib/CleantalkSP/SpbctWP/AdminBannersModule/AdminBanners/AdminBannerTrial.php
index 93c78211d..b8df6deb6 100644
--- a/lib/CleantalkSP/SpbctWP/AdminBannersModule/AdminBanners/AdminBannerTrial.php
+++ b/lib/CleantalkSP/SpbctWP/AdminBannersModule/AdminBanners/AdminBannerTrial.php
@@ -62,7 +62,7 @@ public function __construct(AdminBannersHandler $banners_handler)
'subtitle' => esc_html__('Account status updates every hour or click Settings -> ' . $spbc->data["wl_brandname"] . ' -> Synchronize with Cloud.', 'security-malware-firewall'),
);
- $this->is_settings_page = Get::get('page') === 'spbc';
+ $this->is_settings_page = Get::getString('page') === 'spbc';
}
/**
diff --git a/lib/CleantalkSP/SpbctWP/AdminBannersModule/AdminBanners/AdminBannerWrongKey.php b/lib/CleantalkSP/SpbctWP/AdminBannersModule/AdminBanners/AdminBannerWrongKey.php
index 9150d6c22..a1b97add2 100644
--- a/lib/CleantalkSP/SpbctWP/AdminBannersModule/AdminBanners/AdminBannerWrongKey.php
+++ b/lib/CleantalkSP/SpbctWP/AdminBannersModule/AdminBanners/AdminBannerWrongKey.php
@@ -40,7 +40,7 @@ protected function needToShow()
! $this->banners_handler->spbc->key_is_ok &&
$this->current_screen_id !== 'settings_page_spbc' &&
$this->current_screen_id !== 'settings_page_spbc-network' &&
- ! Cookie::get('spbc_close_wrong_key_banner')
+ ! Cookie::getString('spbc_close_wrong_key_banner')
) {
return true;
}
diff --git a/lib/CleantalkSP/SpbctWP/AdminBannersModule/AdminBannersHandler.php b/lib/CleantalkSP/SpbctWP/AdminBannersModule/AdminBannersHandler.php
index a6d350202..cef342187 100644
--- a/lib/CleantalkSP/SpbctWP/AdminBannersModule/AdminBannersHandler.php
+++ b/lib/CleantalkSP/SpbctWP/AdminBannersModule/AdminBannersHandler.php
@@ -108,7 +108,7 @@ public function dismissBanner()
spbc_check_ajax_referer('spbc_secret_nonce', 'security');
- $banner_id = Post::get('banner_id');
+ $banner_id = Post::getString('banner_id'); // validation is done next line
if ( ! $banner_id ) {
wp_send_json_error(esc_html__('Wrong request.', 'security-malware-firewall'));
diff --git a/lib/CleantalkSP/SpbctWP/DB/SQLSchema.php b/lib/CleantalkSP/SpbctWP/DB/SQLSchema.php
index 6748a7b2d..e686b3c51 100644
--- a/lib/CleantalkSP/SpbctWP/DB/SQLSchema.php
+++ b/lib/CleantalkSP/SpbctWP/DB/SQLSchema.php
@@ -66,14 +66,14 @@ class SQLSchema extends \CleantalkSP\Common\DB\SQLSchema
array('field' => 'detected_at', 'type' => 'int', 'null' => 'yes', 'default' => 'NULL'),
array(
'field' => 'source_type',
- 'type' => 'enum("CORE", "PLUGIN", "THEME")',
+ 'type' => "enum('CORE', 'PLUGIN', 'THEME')",
'null' => 'yes',
'default' => 'NULL',
),
array('field' => 'source', 'type' => 'varchar(300)', 'null' => 'yes', 'default' => 'NULL',),
array(
'field' => 'source_status',
- 'type' => 'set("UP_TO_DATE","OUTDATED","NOT_IN_DIRECTORY","UNKNOWN")',
+ 'type' => "set('UP_TO_DATE','OUTDATED','NOT_IN_DIRECTORY','UNKNOWN')",
'null' => 'yes',
'default' => 'NULL',
),
@@ -82,29 +82,29 @@ class SQLSchema extends \CleantalkSP\Common\DB\SQLSchema
array('field' => 'checked_signatures', 'type' => 'int', 'null' => 'no', 'default' => '0',),
array(
'field' => 'status',
- 'type' => 'enum("UNKNOWN","OK","APPROVED_BY_USER","APPROVED_BY_CT","DENIED_BY_CT","MODIFIED","INFECTED","QUARANTINED", "DENIED_BY_CLOUD", "APPROVED_BY_CLOUD", "ERROR")',
+ 'type' => "enum('UNKNOWN','OK','APPROVED_BY_USER','APPROVED_BY_CT','DENIED_BY_CT','MODIFIED','INFECTED','QUARANTINED', 'DENIED_BY_CLOUD', 'APPROVED_BY_CLOUD', 'ERROR')",
'null' => 'no',
- 'default' => '"UNKNOWN"',
+ 'default' => "'UNKNOWN'",
),
array('field' => 'error_msg', 'type' => 'varchar(1024)', 'null' => 'yes', 'default' => 'NULL',),
array(
'field' => 'severity',
- 'type' => 'enum("CRITICAL", "SUSPICIOUS", "NONE")',
+ 'type' => "enum('CRITICAL', 'SUSPICIOUS', 'NONE')",
'null' => 'yes',
'default' => 'NULL',
),
array('field' => 'weak_spots', 'type' => 'varchar(2048)', 'null' => 'yes', 'default' => 'NULL',),
array('field' => 'difference', 'type' => 'varchar(1024)', 'null' => 'yes', 'default' => 'NULL',),
array('field' => 'last_sent', 'type' => 'int', 'null' => 'yes', 'default' => 'NULL',),
- array('field' => 'fast_hash', 'type' => 'varchar(32)', 'null' => 'yes', 'default' => 'NULL',),
+ array('field' => 'fast_hash', 'type' => 'varchar(32)', 'null' => 'no',),
array('field' => 'full_hash', 'type' => 'varchar(32)', 'null' => 'yes', 'default' => 'NULL',),
array('field' => 'real_full_hash', 'type' => 'varchar(32)', 'null' => 'yes', 'default' => 'NULL',),
array('field' => 'previous_state', 'type' => 'varchar(1024)', 'null' => 'yes', 'default' => 'NULL',),
array('field' => 'q_path', 'type' => 'varchar(1024)', 'null' => 'yes', 'default' => 'NULL',),
array('field' => 'q_time', 'type' => 'int', 'null' => 'yes', 'default' => 'NULL',),
- array('field' => 'pscan_status', 'type' => 'ENUM("DANGEROUS", "SAFE")', 'null' => 'yes', 'default' => 'NULL',),
+ array('field' => 'pscan_status', 'type' => "enum('DANGEROUS', 'SAFE')", 'null' => 'yes', 'default' => 'NULL',),
array('field' => 'pscan_processing_status',
- 'type' => 'ENUM("NEW", "DONE", "ERROR", "IN_SCANER", "NEW_CLOUD", "IN_CLOUD", "IN_SANDBOX", "NEW_SANDBOX", "UNKNOWN")',
+ 'type' => "enum('NEW', 'DONE', 'ERROR', 'IN_SCANER', 'NEW_CLOUD', 'IN_CLOUD', 'IN_SANDBOX', 'NEW_SANDBOX', 'UNKNOWN')",
'null' => 'yes',
'default' => 'NULL',
),
@@ -115,7 +115,7 @@ class SQLSchema extends \CleantalkSP\Common\DB\SQLSchema
),
'indexes' => array(
- array('type' => 'UNIQUE', 'name' => 'KEY', 'body' => '(`fast_hash`)'),
+ array('type' => 'PRIMARY', 'name' => 'KEY', 'body' => '(`fast_hash`)'),
),
),
@@ -187,17 +187,17 @@ class SQLSchema extends \CleantalkSP\Common\DB\SQLSchema
array('field' => 'body', 'type' => 'text', 'null' => 'no',),
array(
'field' => 'type',
- 'type' => 'enum("FILE","CODE_PHP","CODE_HTML","CODE_JS","WAF_RULE")',
+ 'type' => "enum('FILE','CODE_PHP','CODE_HTML','CODE_JS','WAF_RULE')",
'null' => 'no',
),
array(
'field' => 'attack_type',
- 'type' => 'set("SQL_INJECTION","XSS","MALWARE","EXPLOIT","SUSPICIOUS")',
+ 'type' => "set('SQL_INJECTION','XSS','MALWARE','EXPLOIT','SUSPICIOUS')",
'null' => 'no',
),
array(
'field' => 'waf_action',
- 'type' => 'enum("DENY","LOG","ALLOW")',
+ 'type' => "enum('DENY','LOG','ALLOW')",
'null' => 'yes',
'default' => 'NULL',
),
@@ -230,16 +230,16 @@ class SQLSchema extends \CleantalkSP\Common\DB\SQLSchema
array('field' => 'backup_id', 'type' => 'int unsigned', 'null' => 'no', 'extra' => 'AUTO_INCREMENT'),
array(
'field' => 'type',
- 'type' => 'enum("FILE","ALL","SIGNATURES")',
+ 'type' => "enum('FILE','ALL','SIGNATURES')",
'null' => 'no',
- 'default' => '"FILE"',
+ 'default' => "'FILE'",
),
array('field' => 'datetime', 'type' => 'datetime', 'null' => 'no',),
array(
'field' => 'status',
- 'type' => 'enum("PROCESSING", "BACKUPED", "ROLLBACK", "ROLLBACKED", "STOPPED")',
+ 'type' => "enum('PROCESSING', 'BACKUPED', 'ROLLBACK', 'ROLLBACKED', 'STOPPED')",
'null' => 'no',
- 'default' => '"PROCESSING"',
+ 'default' => "'PROCESSING'",
),
),
'indexes' => array(
@@ -395,7 +395,7 @@ class SQLSchema extends \CleantalkSP\Common\DB\SQLSchema
array('field' => 'ip_entry', 'type' => 'varchar(50)', 'null' => 'yes',),
array(
'field' => 'status',
- 'type' => 'enum("PASS","PASS_BY_TRUSTED_NETWORK","PASS_BY_WHITELIST","DENY","DENY_BY_NETWORK","DENY_BY_DOS","DENY_BY_WAF_BLOCKER","DENY_BY_WAF_XSS","DENY_BY_WAF_SQL","DENY_BY_WAF_FILE","DENY_BY_WAF_EXPLOIT","DENY_BY_SEC_FW","DENY_BY_SPAM_FW","DENY_BY_BFP")',
+ 'type' => "enum('PASS','PASS_BY_TRUSTED_NETWORK','PASS_BY_WHITELIST','DENY','DENY_BY_NETWORK','DENY_BY_DOS','DENY_BY_WAF_BLOCKER','DENY_BY_WAF_XSS','DENY_BY_WAF_SQL','DENY_BY_WAF_FILE','DENY_BY_WAF_EXPLOIT','DENY_BY_SEC_FW','DENY_BY_SPAM_FW','DENY_BY_BFP')",
'null' => 'yes',
'default' => 'NULL',
'extra' => '',
diff --git a/lib/CleantalkSP/SpbctWP/FSWatcher/Controller.php b/lib/CleantalkSP/SpbctWP/FSWatcher/Controller.php
index d3ef37f40..79f07b869 100644
--- a/lib/CleantalkSP/SpbctWP/FSWatcher/Controller.php
+++ b/lib/CleantalkSP/SpbctWP/FSWatcher/Controller.php
@@ -33,9 +33,9 @@ class Controller
public function __construct(FSWatcherParams $params)
{
self::$params = $params;
- $is_fs_watcher_action = Post::get('action') === 'spbct_fswatcher_compare' ||
- Post::get('action') === 'spbct_fswatcher_view_file' ||
- Post::get('action') === 'spbct_fswatcher_create_snapshot';
+ $is_fs_watcher_action = Post::getString('action') === 'spbct_fswatcher_compare' ||
+ Post::getString('action') === 'spbct_fswatcher_view_file' ||
+ Post::getString('action') === 'spbct_fswatcher_create_snapshot';
if ( defined('DOING_AJAX') && DOING_AJAX && $is_fs_watcher_action) {
$this->checkRateLimit();
diff --git a/lib/CleantalkSP/SpbctWP/Firewall.php b/lib/CleantalkSP/SpbctWP/Firewall.php
index b9e7700fb..17a68ff79 100644
--- a/lib/CleantalkSP/SpbctWP/Firewall.php
+++ b/lib/CleantalkSP/SpbctWP/Firewall.php
@@ -70,18 +70,18 @@ public function updateLog(Result $fw_result)
: '',
'page_url' => substr(
addslashes(
- (Server::get('HTTPS') !== 'off' ? 'https://' : 'http://') . Server::get('HTTP_HOST') . Server::get(
+ (Server::getString('HTTPS') !== 'off' ? 'https://' : 'http://') . Server::getString('HTTP_HOST') . Server::getString(
'REQUEST_URI'
)
),
0,
4096
),
- 'http_user_agent' => Server::get('HTTP_USER_AGENT')
- ? addslashes(htmlspecialchars(substr(Server::get('HTTP_USER_AGENT'), 0, 300)))
+ 'http_user_agent' => Server::getString('HTTP_USER_AGENT')
+ ? addslashes(htmlspecialchars(substr(Server::getString('HTTP_USER_AGENT'), 0, 300)))
: 'unknown',
- 'request_method' => Server::get('REQUEST_METHOD'),
- 'x_forwarded_for' => addslashes(htmlspecialchars(substr(Server::get('HTTP_X_FORWARDED_FOR'), 0, 15))),
+ 'request_method' => Server::getString('REQUEST_METHOD'),
+ 'x_forwarded_for' => addslashes(htmlspecialchars(substr(Server::getString('HTTP_X_FORWARDED_FOR'), 0, 15))),
'network' => $fw_result->network,
'mask' => $fw_result->mask,
'is_personal' => $fw_result->is_personal,
diff --git a/lib/CleantalkSP/SpbctWP/Firewall/FW.php b/lib/CleantalkSP/SpbctWP/Firewall/FW.php
index d02ff1046..021732259 100644
--- a/lib/CleantalkSP/SpbctWP/Firewall/FW.php
+++ b/lib/CleantalkSP/SpbctWP/Firewall/FW.php
@@ -43,10 +43,10 @@ public function ipAppendAdditional(&$ips)
{
$this->real_ip = isset($ips['real']) ? $ips['real'] : null;
- $test_ip = Get::get('spbct_test_ip');
- if ( IP::validate($test_ip) && Get::get('spbct_test') === md5($this->api_key) ) {
+ $test_ip = Get::getString('spbct_test_ip');
+ if ( IP::validate($test_ip) && Get::getString('spbct_test') === md5($this->api_key) ) {
$ips['test'] = $test_ip;
- $this->test_ip = $test_ip;
+ $this->test_ip = (bool) $test_ip;
$this->test = true;
}
}
@@ -719,10 +719,10 @@ public static function updateWriteToDbExclusions(
$query = 'INSERT INTO `' . $data_table__personal_v4 . '` (network,mask,status) VALUES ';
//Exclusion for servers IP (SERVER_ADDR)
- if ( Server::get('HTTP_HOST') ) {
+ if ( Server::getString('HTTP_HOST') ) {
// Exceptions for local hosts
if ( ! in_array(Server::getDomain(), array('lc', 'loc', 'lh')) ) {
- $exclusions[] = \CleantalkSP\SpbctWP\Helpers\Helper::resolveDNS(Server::get('HTTP_HOST'));
+ $exclusions[] = \CleantalkSP\SpbctWP\Helpers\Helper::resolveDNS(Server::getString('HTTP_HOST'));
$exclusions[] = '127.0.0.1';
// And delete all 127.0.0.1 entries for local hosts
diff --git a/lib/CleantalkSP/SpbctWP/Firewall/FirewallModule.php b/lib/CleantalkSP/SpbctWP/Firewall/FirewallModule.php
index 71defd0ee..1a4157ead 100644
--- a/lib/CleantalkSP/SpbctWP/Firewall/FirewallModule.php
+++ b/lib/CleantalkSP/SpbctWP/Firewall/FirewallModule.php
@@ -131,7 +131,7 @@ public function _die(Result $result) // phpcs:ignore PSR2.Methods.MethodDeclarat
$this->state->settings['fw__custom_message'],
$allowed_html
) : '',
- '{TEST_TITLE}' => Get::get('spbct_test')
+ '{TEST_TITLE}' => Get::getString('spbct_test')
? __('This is the testing page for Security FireWall', 'security-malware-firewall')
: '',
'{REASON}' => $reason,
@@ -143,7 +143,7 @@ public function _die(Result $result) // phpcs:ignore PSR2.Methods.MethodDeclarat
'{REMOTE_ADDRESS}' => $result->ip,
'{SERVICE_ID}' => isset($this->state->data['service_id']) ? $this->state->data['service_id'] : '',
- '{HOST}' => Server::get('HTTP_HOST'),
+ '{HOST}' => Server::getString('HTTP_HOST'),
'{GENERATED}' => '
The page was generated at '
. date("D, d M Y H:i:s")
. ' ',
diff --git a/lib/CleantalkSP/SpbctWP/Firewall/UploadChecker.php b/lib/CleantalkSP/SpbctWP/Firewall/UploadChecker.php
index 87b042d56..f7c78bb8d 100644
--- a/lib/CleantalkSP/SpbctWP/Firewall/UploadChecker.php
+++ b/lib/CleantalkSP/SpbctWP/Firewall/UploadChecker.php
@@ -124,8 +124,8 @@ private function runCheckForFilesGlobalVariable($global_files_variable)
}
$file_is_packed = false;
- if (Server::get('QUERY_STRING') !== 'action=upload-plugin' &&
- Server::get('QUERY_STRING') !== 'action=upload-theme' &&
+ if (Server::get('QUERY_STRING', null, 'url') !== 'action=upload-plugin' &&
+ Server::get('QUERY_STRING', null, 'url') !== 'action=upload-theme' &&
in_array(Data::getMIMEType($file_path), $this->waf_file_mime_check_zip)
) {
$file_is_packed = true;
@@ -436,7 +436,7 @@ public static function uploadCheckerGetLastBlockInfo()
global $wpdb, $spbc;
- $timestamp = intval(Post::get('timestamp'));
+ $timestamp = intval(Post::getInt('timestamp'));
// Select only latest ones.
$result = $wpdb->get_results(
@@ -517,21 +517,21 @@ public function logDenyUploadedModule(Result $upload_checker_result)
: '';
$page_url = substr(
addslashes(
- (Server::get('HTTPS') !== 'off' ? 'https://' : 'http://')
- . Server::get('HTTP_HOST')
- . Server::get('REQUEST_URI')
+ (Server::getString('HTTPS') !== 'off' ? 'https://' : 'http://')
+ . Server::getString('HTTP_HOST')
+ . Server::get('REQUEST_URI', null, 'url')
),
0,
4096
);
- $http_user_agent = Server::get('HTTP_USER_AGENT')
- ? addslashes(htmlspecialchars(substr(Server::get('HTTP_USER_AGENT'), 0, 300)))
+ $http_user_agent = Server::getString('HTTP_USER_AGENT')
+ ? addslashes(htmlspecialchars(substr(Server::getString('HTTP_USER_AGENT'), 0, 300)))
: 'unknown';
$ip = $upload_checker_result->ip;
$time = time();
$status = $upload_checker_result->status;
- $request_method = Server::get('REQUEST_METHOD');
- $x_forwarded_for = addslashes(htmlspecialchars(substr(Server::get('HTTP_X_FORWARDED_FOR'), 0, 15)));
+ $request_method = Server::getString('REQUEST_METHOD');
+ $x_forwarded_for = addslashes(htmlspecialchars(substr(Server::getString('HTTP_X_FORWARDED_FOR'), 0, 15)));
$network = $upload_checker_result->network;
$mask = $upload_checker_result->mask;
$is_personal = $upload_checker_result->is_personal;
diff --git a/lib/CleantalkSP/SpbctWP/Firewall/WAF.php b/lib/CleantalkSP/SpbctWP/Firewall/WAF.php
index 43ad57e47..0d5932bcd 100644
--- a/lib/CleantalkSP/SpbctWP/Firewall/WAF.php
+++ b/lib/CleantalkSP/SpbctWP/Firewall/WAF.php
@@ -77,8 +77,8 @@ public function check()
$data_array = array();
$query_str = '';
- if (Server::get('QUERY_STRING')) {
- $query_str = urldecode(Server::get('QUERY_STRING'));
+ if (Server::get('QUERY_STRING', null, 'url')) {
+ $query_str = urldecode(Server::get('QUERY_STRING', null, 'url'));
} else if (@file_get_contents('php://input')) {
$query_str = file_get_contents('php://input');
}
@@ -303,21 +303,21 @@ public function log(Result $waf_result)
: '';
$page_url = substr(
addslashes(
- (Server::get('HTTPS') !== 'off' ? 'https://' : 'http://')
- . Server::get('HTTP_HOST')
- . Server::get('REQUEST_URI')
+ (Server::getString('HTTPS') !== 'off' ? 'https://' : 'http://')
+ . Server::getString('HTTP_HOST')
+ . Server::get('REQUEST_URI', null, 'url')
),
0,
4096
);
- $http_user_agent = Server::get('HTTP_USER_AGENT')
- ? addslashes(htmlspecialchars(substr(Server::get('HTTP_USER_AGENT'), 0, 300)))
+ $http_user_agent = Server::getString('HTTP_USER_AGENT')
+ ? addslashes(htmlspecialchars(substr(Server::getString('HTTP_USER_AGENT'), 0, 300)))
: 'unknown';
$ip = $waf_result->ip;
$time = time();
$status = $waf_result->status;
- $request_method = Server::get('REQUEST_METHOD');
- $x_forwarded_for = addslashes(htmlspecialchars(substr(Server::get('HTTP_X_FORWARDED_FOR'), 0, 15)));
+ $request_method = Server::getString('REQUEST_METHOD');
+ $x_forwarded_for = addslashes(htmlspecialchars(substr(Server::getString('HTTP_X_FORWARDED_FOR'), 0, 15)));
$network = $waf_result->network;
$mask = $waf_result->mask;
$is_personal = $waf_result->is_personal;
diff --git a/lib/CleantalkSP/SpbctWP/Helpers/HTTP.php b/lib/CleantalkSP/SpbctWP/Helpers/HTTP.php
index 05d6c810a..e0c6ea6f5 100644
--- a/lib/CleantalkSP/SpbctWP/Helpers/HTTP.php
+++ b/lib/CleantalkSP/SpbctWP/Helpers/HTTP.php
@@ -25,7 +25,10 @@ class HTTP extends \CleantalkSP\Common\Helpers\HTTP
public static function getCleantalksAPIServersFromDNS()
{
$servers = [];
- $dns_records = dns_get_record('api.cleantalk.org', DNS_A);
+ $dns_records = @dns_get_record('api.cleantalk.org', DNS_A);
+ if (false === $dns_records) {
+ $dns_records = array();
+ }
foreach ($dns_records as $record) {
if (isset($record['ip'])) {
diff --git a/lib/CleantalkSP/SpbctWP/ListTable.php b/lib/CleantalkSP/SpbctWP/ListTable.php
index d4a24b4ad..9053f8654 100644
--- a/lib/CleantalkSP/SpbctWP/ListTable.php
+++ b/lib/CleantalkSP/SpbctWP/ListTable.php
@@ -556,9 +556,9 @@ public static function ajaxBulkActionHandler()
{
spbc_check_ajax_referer('spbc_secret_nonce', 'security');
- $ids = spbc_scanner_get_files_by_category(Post::get('status', null, 'word'));
+ $ids = spbc_scanner_get_files_by_category(Post::getString('status'));
- switch ( Post::get('add_action', null, 'word') ) {
+ switch ( Post::getString('add_action') ) {
case 'approve':
$out = spbc_scanner_file_approve__bulk($ids);
break;
@@ -649,7 +649,7 @@ public static function ajaxRowActionHandler()
{
spbc_check_ajax_referer('spbc_secret_nonce', 'security');
- $action = Post::get('add_action', null, 'word');
+ $action = Post::getString('add_action');
$is_frontend_malware_action = $action === 'disapprove_page' || $action === 'approve_page';
if ( $action !== 'restore' && ! $is_frontend_malware_action && strpos($action, 'oscron_task') === false ) {
@@ -761,7 +761,7 @@ public static function ajaxRowActionHandlerDisableOSCronTask()
public static function ajaxRowActionHandlerApprove()
{
- $out = spbc_scanner_file_approve(true, Post::get('id', null, 'word'));
+ $out = spbc_scanner_file_approve(true, Post::getString('id'));
if ( empty($out['error']) ) {
$out = array(
@@ -780,7 +780,7 @@ public static function ajaxRowActionHandlerApprove()
public static function ajaxRowActionHandlerDisapprove()
{
- $out = spbc_scanner_file_disapprove(true, Post::get('id', null, 'word'));
+ $out = spbc_scanner_file_disapprove(true, Post::getString('id'));
if ( empty($out['error']) ) {
$out = array(
@@ -819,7 +819,7 @@ public static function ajaxRowActionHandlerPageApprovementProcess($action)
public static function ajaxRowActionHandlerDelete()
{
- $out = spbc_scanner_file_delete(true, Post::get('id', null, 'word'));
+ $out = spbc_scanner_file_delete(true, Post::getString('id'));
if ( empty($out['error']) ) {
$out = array(
@@ -837,7 +837,7 @@ public static function ajaxRowActionHandlerDelete()
public static function ajaxRowActionHandlerReplace()
{
- $out = spbc_scanner_file_replace(true, Post::get('id', null, 'word'));
+ $out = spbc_scanner_file_replace(true, Post::getString('id'));
if ( empty($out['error']) ) {
$out = array(
@@ -855,7 +855,7 @@ public static function ajaxRowActionHandlerReplace()
public static function ajaxRowActionHandlerSend()
{
- $file_fast_hash = Post::get('id', null, 'word');
+ $file_fast_hash = Post::getString('id');
$out = spbc_scanner_file_send(true, $file_fast_hash);
if ( empty($out['error']) ) {
@@ -905,7 +905,7 @@ public static function ajaxRowActionHandlerSend()
public static function ajaxRowActionHandlerQuarantine()
{
- $out = spbc_scanner_file_quarantine(true, Post::get('id', null, 'word'));
+ $out = spbc_scanner_file_quarantine(true, Post::getString('id'));
if ( empty($out['error']) ) {
$out = array(
@@ -923,7 +923,7 @@ public static function ajaxRowActionHandlerQuarantine()
public static function ajaxRowActionHandlerQuarantineRestore()
{
- $out = spbc_scanner_file_quarantine__restore(true, Post::get('id', null, 'word'));
+ $out = spbc_scanner_file_quarantine__restore(true, Post::getString('id'));
if ( empty($out['error']) ) {
$out = array(
@@ -946,7 +946,7 @@ private static function ajaxRowActionHandlerDownload()
public static function ajaxRowActionHandlerCheckAnalysisStatus()
{
- $out = spbc_scanner_pscan_check_analysis_status(true, Post::get('id', null, 'word'));
+ $out = spbc_scanner_pscan_check_analysis_status(true, Post::getString('id'));
if ( empty($out['error']) ) {
$out = array(
@@ -969,9 +969,9 @@ public static function ajaxPaginationHandler()
{
spbc_check_ajax_referer('spbc_secret_nonce', 'security');
- $type = Post::get('type', 'word');
+ $type = Post::getString('type');
$args = spbc_list_table__get_args_by_type($type);
- $args['pagination']['page'] = Post::get('page', 'int', null);
+ $args['pagination']['page'] = Post::getInt('page');
$table = new ListTable($args);
$table->getData();
$table->display();
@@ -983,9 +983,9 @@ public static function ajaxSortHandler()
{
spbc_check_ajax_referer('spbc_secret_nonce', 'security');
- $type = Post::get('type', 'word');
- $order_by = Post::get('order_by', null, 'word');
- $order = Post::get('order', null, 'word');
+ $type = Post::getString('type');
+ $order_by = Post::getString('order_by');
+ $order = Post::getString('order');
$args = spbc_list_table__get_args_by_type($type);
$args['order_by'] = array((string)$order_by => $order);
$table = new ListTable($args);
@@ -999,7 +999,7 @@ public static function ajaxSwitchTable()
{
spbc_check_ajax_referer('spbc_secret_nonce', 'security');
- $type = Post::get('type', 'word');
+ $type = Post::getString('type');
$args = spbc_list_table__get_args_by_type($type);
$table = new ListTable($args);
if ($table->type == 'links') {
@@ -1038,7 +1038,7 @@ public static function stripslashesArray($arr)
*/
public static function ajaxRowActionHandlerCopyFileInfo()
{
- $file_id = Post::get('id', null, 'word');
+ $file_id = Post::getString('id');
if ( !empty($file_id) ) {
$file_info = spbc_scanner_get_file_by_id($file_id);
$file_info = array(
diff --git a/lib/CleantalkSP/SpbctWP/RemoteCalls.php b/lib/CleantalkSP/SpbctWP/RemoteCalls.php
index 7862e8039..e2cc09cfa 100644
--- a/lib/CleantalkSP/SpbctWP/RemoteCalls.php
+++ b/lib/CleantalkSP/SpbctWP/RemoteCalls.php
@@ -33,19 +33,19 @@ protected static function filter_before_action() // phpcs:ignore PSR1.Methods.Ca
}
// Delay before perform action
- if ( Request::get('delay') ) {
+ if ( Request::getString('delay') ) {
// Do not make remote call because the website is in maintenance mode
if ( wp_is_maintenance_mode() ) {
return true;
}
- sleep((int)Request::get('delay'));
+ sleep(Request::getInt('delay'));
- $params = Get::get('delay') ? $_GET : $_POST;
+ $params = Get::getString('delay') ? $_GET : $_POST;
unset($params['delay']);
return static::performToHost(
- Request::get('spbc_remote_action'),
+ Request::getString('spbc_remote_action'),
$params,
array('async'),
false
@@ -158,7 +158,7 @@ public static function action__drop_security_firewall() // phpcs:ignore PSR1.Met
*/
public static function action__download__quarantine_file() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
{
- $result = spbc_scanner_file_download(true, Request::get('file_id'));
+ $result = spbc_scanner_file_download(true, Request::getString('file_id'));
if ( empty($result['error']) ) {
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' . $result['file_name']);
@@ -185,13 +185,13 @@ public static function action__update_settings() // phpcs:ignore PSR1.Methods.Ca
global $spbc;
// Try to get setting from JSON
- $incoming_settings = json_decode(Request::get('settings'), true);
+ $incoming_settings = json_decode(Request::getString('settings'), true);
// Try to get setting from STRING
if ( ! $incoming_settings ) {
foreach ( $spbc->default_settings as $setting_name => $_setting_value ) {
- if ( Request::get($setting_name) !== '' ) {
- $incoming_settings[$setting_name] = Request::get($setting_name);
+ if ( Request::getString($setting_name) !== '' ) {
+ $incoming_settings[$setting_name] = Request::getString($setting_name);
}
}
}
@@ -232,12 +232,12 @@ public static function action__cron_update_task() // phpcs:ignore PSR1.Methods.C
$update_result = false;
- if ( Request::get('task') && Request::get('handler') && Request::get('period') && Request::get('first_call') ) {
+ if ( Request::getString('task') && Request::getString('handler') && Request::getString('period') && Request::getString('first_call') ) {
$update_result = Cron::updateTask(
- Request::get('task'),
- Request::get('handler'),
- (int)Request::get('period'),
- (int)Request::get('first_call')
+ Request::getString('task'),
+ Request::getString('handler'),
+ Request::getInt('period'),
+ Request::getInt('first_call')
);
}
@@ -248,7 +248,7 @@ public static function action__cron_update_task() // phpcs:ignore PSR1.Methods.C
*/
public static function action__rollback_repair() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
{
- $result = spbc_rollback(Request::get('backup_id'));
+ $result = spbc_rollback(Request::getString('backup_id'));
die(empty($result['error'])
? 'OK'
: 'FAIL ' . json_encode(array('error' => $result['error'])));
@@ -270,7 +270,7 @@ public static function action__scanner__controller() // phpcs:ignore PSR1.Method
*/
public static function action__scanner__check_dir() // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
{
- $file_infos = Get::get('file_infos');
+ $file_infos = Get::getArray('file_infos');
if ( ! is_array($file_infos) || ! $file_infos ) {
wp_send_json(array('error' => 'INVALID_FILE_INFOS'));
return;
@@ -331,7 +331,7 @@ public static function action__debug() // phpcs:ignore PSR1.Methods.CamelCapsMet
$out['errors'] = $spbc->errors;
$out['debug'] = $spbc->debug;
$out['queue'] = get_option('spbc_fw_update_queue');
- $out['servers_connection'] = Get::get('do_test_connection') ? spbc_test_connection() : 'skipped, add &do_test_connection to run this';
+ $out['servers_connection'] = Get::getString('do_test_connection') ? spbc_test_connection() : 'skipped, add &do_test_connection to run this';
$out['plugins'] = $spbc->plugins;
$out['themes'] = $spbc->themes;
$out['transactions'] = $wpdb->get_results("SELECT * FROM {$wpdb->options} WHERE option_name LIKE 'spbc_transaction__%'");
@@ -367,12 +367,12 @@ public static function action__post_api_key() // phpcs:ignore PSR1.Methods.Camel
{
global $spbc;
- $key = trim(Request::get('api_key'));
+ $key = trim(Request::getString('api_key'));
if ( !spbc_api_key__is_correct($key) ) {
wp_send_json(['FAIL' => ['error' => 'Api key is incorrect']]);
}
- $template_id = Request::get('apply_template_id');
+ $template_id = Request::getString('apply_template_id');
if ( !empty($template_id) ) {
$templates = CleantalkSettingsTemplates::get_options_template($key);
if ( !empty($templates) ) {
@@ -463,7 +463,7 @@ public static function action__run_service_template_get() // phpcs:ignore PSR1.M
/**
* $template_id validation
*/
- $template_id = Request::get('template_id');
+ $template_id = Request::getString('template_id');
if ( empty($template_id) || !is_string($template_id) ) {
throw new \InvalidArgumentException($error_hat . 'bad param template_id');
@@ -491,9 +491,9 @@ public static function action__update_pscan_statuses() // phpcs:ignore PSR1.Meth
//get db
$db = DB::getInstance();
//check if data is provided
- if (Post::get('file_pscan_ids')) {
+ if (Post::getString('file_pscan_ids')) {
//get data from json from POST
- $file_pscan_ids = json_decode(Post::get('file_pscan_ids'), true);
+ $file_pscan_ids = json_decode(Post::getString('file_pscan_ids'), true);
//validate values
if ( $file_pscan_ids === null ) {
@@ -518,7 +518,7 @@ public static function action__update_pscan_statuses() // phpcs:ignore PSR1.Meth
$result = $db->fetchAll($query, OBJECT_K);
} else {
//if no post data but get paramter persists update very file
- if (Get::get('update_all')) {
+ if (Get::getString('update_all')) {
//prepare to SQL
$query = 'SELECT fast_hash FROM ' . SPBC_TBL_SCAN_FILES . ' WHERE pscan_file_id IS NOT NULL';
$result = $db->fetchAll($query, OBJECT_K);
diff --git a/lib/CleantalkSP/SpbctWP/RenameLoginPage.php b/lib/CleantalkSP/SpbctWP/RenameLoginPage.php
index 378e4d2db..6556405c8 100644
--- a/lib/CleantalkSP/SpbctWP/RenameLoginPage.php
+++ b/lib/CleantalkSP/SpbctWP/RenameLoginPage.php
@@ -105,7 +105,7 @@ public function wpLoaded()
global $pagenow;
- if ( !Post::get('post_password') || Get::get('action') !== 'postpass' ) {
+ if ( !Post::getString('post_password') || Get::getString('action') !== 'postpass' ) {
// Prevent redirecting from /wp-admin/ to login_url
if (
!defined('DOING_AJAX') &&
@@ -122,7 +122,7 @@ public function wpLoaded()
if ( $pagenow === 'wp-login.php' && $this->using_permalink && !$this->isOnPage($this->login_slug) ) {
wp_safe_redirect(
$this->trailSlash($this->login_url)
- . (Server::get('QUERY_STRING') ? '?' . $_SERVER['QUERY_STRING'] : '')
+ . (Server::get('QUERY_STRING', null, 'url') ? '?' . Server::get('QUERY_STRING', null, 'url') : '')
);
die();
}
diff --git a/lib/CleantalkSP/SpbctWP/Scanner/OSCron/View/OSCronLocale.php b/lib/CleantalkSP/SpbctWP/Scanner/OSCron/View/OSCronLocale.php
index 220e255ed..8fa8f0c7a 100644
--- a/lib/CleantalkSP/SpbctWP/Scanner/OSCron/View/OSCronLocale.php
+++ b/lib/CleantalkSP/SpbctWP/Scanner/OSCron/View/OSCronLocale.php
@@ -46,7 +46,7 @@ public function init()
$this->error__missing_property = __('property is no set', 'security-malware-firewall');
$this->error__invalid_cron_expression = __('Invalid cron expression', 'security-malware-firewall');
$this->error__task_not_found = __('Task tried to update is not found', 'security-malware-firewall');
- $this->settings__accordion_tab_description = __('This section provides an overview of scheduled cron jobs on server that perform automated tasks. Check your cron jobs for suspicious entries and delete, modify, or send them to the CleanTalk Cloud for analysis necessary to ensure security.', 'security-malware-firewall');
+ $this->settings__accordion_tab_description = __('This section provides an overview of scheduled cron jobs on server that perform automated tasks. Check your cron jobs for suspicious entries and delete or modify entries.', 'security-malware-firewall');
$this->settings__option_title = __('Operating system cron tasks analysis', 'security-malware-firewall');
$this->settings__option_description = __('This functional provides an overview of scheduled cron jobs on server that perform automated tasks.', 'security-malware-firewall');
}
diff --git a/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php b/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php
index 4fb6b3368..d2192e490 100644
--- a/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php
+++ b/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php
@@ -102,9 +102,9 @@ public function __construct($stage = '', $offset = null, $amount = null, $root_d
$this->db = DB::getInstance();
- $this->stage = isset($stage) ? $stage : Request::get('stage');
- $this->amount = isset($amount) ? (int)$amount : (int)Request::get('amount');
- $this->offset = isset($offset) ? (int)$offset : (int)Request::get('offset');
+ $this->stage = isset($stage) ? $stage : Request::getString('stage');
+ $this->amount = isset($amount) ? (int)$amount : Request::getInt('amount');
+ $this->offset = isset($offset) ? (int)$offset : Request::getInt('offset');
$this->root = $root_dir ?: realpath(ABSPATH);
// Crunch for cure backups
@@ -182,7 +182,7 @@ public static function controllerBackground($transaction_id = null, $stage = nul
{
global $spbc;
- $transaction_id = $transaction_id ?: Request::get('transaction_id'); // @todo cast to int by Variables
+ $transaction_id = $transaction_id ?: Request::getInt('transaction_id');
if ( (int)$transaction_id !== (int)Transaction::get('background_scanner')->getTID() ) {
return true;
@@ -299,7 +299,7 @@ public static function controllerFront()
}
$scanner = new self();
- $method_name = str_replace('spbc_scanner_', '', Request::get('method'));
+ $method_name = str_replace('spbc_scanner_', '', Request::getString('method'));
$out = method_exists(__CLASS__, $method_name)
? $scanner->$method_name()
@@ -509,7 +509,7 @@ public function countModules()
*/
public function get_modules_hashes($amount = null, $offset = null) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
{
- global $spbc;
+ global $spbc, $wp_filter;
$amount = isset($amount) ? (int)$amount : $this->amount;
$offset = isset($offset) ? (int)$offset : $this->offset;
@@ -593,10 +593,34 @@ public function get_modules_hashes($amount = null, $offset = null) // phpcs:igno
);
}
} else {
- $result_wp_api_modules = themes_api(
- $modules_entry_type,
- array('slug' => $module_slug, 'fields' => array('Version' => true))
- );
+ try {
+ // First check if themes_api function exists
+ if (!function_exists('themes_api')) {
+ require_once(ABSPATH . 'wp-admin/includes/theme.php');
+ }
+
+ // Store existing filters
+ $stored_filters = isset($wp_filter['themes_api']) ? $wp_filter['themes_api'] : null;
+
+ // Remove all themes_api filters temporarily
+ if (isset($wp_filter['themes_api'])) {
+ unset($wp_filter['themes_api']);
+ }
+
+ // Make the API call
+ $result_wp_api_modules = themes_api(
+ $modules_entry_type,
+ array('slug' => $module_slug, 'fields' => array('Version' => true))
+ );
+
+ // Restore original filters
+ if ($stored_filters !== null) {
+ $wp_filter['themes_api'] = $stored_filters;
+ }
+ } catch (\Exception $e) {
+ error_log('Security Scanner - Theme API error for ' . $module_slug . ': ' . $e->getMessage());
+ $result_wp_api_modules = new \WP_Error('themes_api_failed', 'Theme API call failed');
+ }
}
if ( ! is_wp_error($result_wp_api_modules) && isset($result_wp_api_modules->version) ) {
@@ -775,9 +799,8 @@ public function clean_results($offset = null, $amount = 50000) // phpcs:ignore P
*/
public function countFilesByStatusAndChecked($status = '', $caller = '')
{
- $status = stripslashes(Request::get('status')) ?: $status;
- //$checked = stripslashes( Request::get('checked') ) ?: $checked; #todo What was this for?
- if ( Request::get('checked') ) {
+ $status = stripslashes(Request::getString('status')) ?: $status;
+ if ( Request::getString('checked') ) {
error_log(
'countFilesByStatusAndChecked: $_GET[\'checked\'] parameter found, but not handled in the method ' . var_export(
$_GET,
@@ -1254,7 +1277,7 @@ public function signature_analysis($status = 'UNKNOWN,MODIFIED,OK,INFECTED,ERROR
{
global $spbc;
- $status_raw = isset($status) ? $status : stripslashes(Request::get('status'));
+ $status_raw = isset($status) ? $status : stripslashes(Request::getString('status'));
if ( ! preg_match('#^[A-Z,_]+$#', $status_raw) ) {
return array('error' => 'BAD_PARAMS');
}
@@ -1472,7 +1495,7 @@ public function signature_analysis($status = 'UNKNOWN,MODIFIED,OK,INFECTED,ERROR
public function heuristic_analysis($status = 'UNKNOWN,MODIFIED,OK,INFECTED,ERROR', $offset = null, $amount = null) // phpcs:ignore PSR1.Methods.CamelCapsMethodName.NotCamelCaps
{
global $spbc;
- $status_raw = isset($status) ? $status : stripslashes(Request::get('status'));
+ $status_raw = isset($status) ? $status : stripslashes(Request::getString('status'));
if ( ! preg_match('#^[A-Z,_]+$#', $status_raw) ) {
return array('error' => 'BAD_PARAMS');
}
diff --git a/lib/CleantalkSP/SpbctWP/Scanner/Stages/SendResultsStage.php b/lib/CleantalkSP/SpbctWP/Scanner/Stages/SendResultsStage.php
index ee8285c03..ac2b9821b 100644
--- a/lib/CleantalkSP/SpbctWP/Scanner/Stages/SendResultsStage.php
+++ b/lib/CleantalkSP/SpbctWP/Scanner/Stages/SendResultsStage.php
@@ -98,7 +98,7 @@ private function sendFiles($error)
$spbc->data['scanner']['last_sent'] = current_time('timestamp');
$spbc->data['scanner']['last_scan'] = current_time('timestamp');
$spbc->data['scanner']['scan_finish_timestamp'] = time();
- $spbc->data['scanner']['last_scan_amount'] = Request::get('total_scanned') ?: $dto->total_scan_files;
+ $spbc->data['scanner']['last_scan_amount'] = Request::getString('total_scanned') ?: $dto->total_scan_files;
$spbc->data['scanner']['signatures_found'] = []; // Clearing ids of the signatures found
}
diff --git a/lib/CleantalkSP/SpbctWP/Scanner/Surface.php b/lib/CleantalkSP/SpbctWP/Scanner/Surface.php
index e12f5bf62..289c1936d 100644
--- a/lib/CleantalkSP/SpbctWP/Scanner/Surface.php
+++ b/lib/CleantalkSP/SpbctWP/Scanner/Surface.php
@@ -493,41 +493,51 @@ public function countFilesMandatory($files)
*/
public function countFilesInDir($main_path)
{
- $iterator = new \RecursiveIteratorIterator(
- new \RecursiveDirectoryIterator($main_path, \FilesystemIterator::SKIP_DOTS),
- \RecursiveIteratorIterator::SELF_FIRST
- );
-
- foreach ($iterator as $fileInfo) {
- if ($fileInfo->isLink()) {
- continue; // Skip symlinks
- }
+ try {
+ $iterator = new \RecursiveIteratorIterator(
+ new \RecursiveDirectoryIterator($main_path, \FilesystemIterator::SKIP_DOTS),
+ \RecursiveIteratorIterator::SELF_FIRST
+ );
- if ($fileInfo->isFile()) {
- $filename = $fileInfo->getFileName();
- $currentFileExtension = pathinfo($filename, PATHINFO_EXTENSION);
-
- // Extensions filter
- if ( $this->ext_except || $this->ext ) {
- if (
- ! $this->hasFileAllowedExtension(
- $currentFileExtension,
- $this->ext_except,
- $this->ext,
- $fileInfo->getPathname()
- )
- ) {
- continue;
+ foreach ($iterator as $fileInfo) {
+ try {
+ if ($fileInfo->isLink()) {
+ continue; // Skip symlinks
}
- }
- // Filenames exception filter
- if ( ! empty($this->files_except) && in_array($fileInfo->getPathname(), $this->files_except, true) ) {
+ if ($fileInfo->isFile()) {
+ $filename = $fileInfo->getFileName();
+ $currentFileExtension = pathinfo($filename, PATHINFO_EXTENSION);
+
+ // Extensions filter
+ if ( $this->ext_except || $this->ext ) {
+ if (
+ ! $this->hasFileAllowedExtension(
+ $currentFileExtension,
+ $this->ext_except,
+ $this->ext,
+ $fileInfo->getPathname()
+ )
+ ) {
+ continue;
+ }
+ }
+
+ // Filenames exception filter
+ if ( ! empty($this->files_except) && in_array($fileInfo->getPathname(), $this->files_except, true) ) {
+ continue;
+ }
+
+ $this->output_files_count++;
+ }
+ } catch (\RuntimeException $e) {
+ // Skip files/directories we can't access
continue;
}
-
- $this->output_files_count++;
}
+ } catch (\UnexpectedValueException $e) {
+ // Skip directories we can't access
+ return;
}
}
diff --git a/lib/CleantalkSP/SpbctWP/SpbcEnqueue.php b/lib/CleantalkSP/SpbctWP/SpbcEnqueue.php
index e0b02d44c..506b8357e 100644
--- a/lib/CleantalkSP/SpbctWP/SpbcEnqueue.php
+++ b/lib/CleantalkSP/SpbctWP/SpbcEnqueue.php
@@ -3,10 +3,422 @@
namespace CleantalkSP\SpbctWP;
use CleantalkSP\Common\Enqueue\Enqueue;
+use CleantalkSP\SpbctWP\Scanner\ScannerQueue;
+use CleantalkSP\SpbctWP\Variables\Cookie;
class SpbcEnqueue extends Enqueue
{
protected $plugin_version = SPBC_VERSION;
protected $assets_path = SPBC_PATH;
protected $plugin_path = SPBC_PLUGIN_DIR;
+
+ /**
+ * Register stylesheet and scripts.
+ * @psalm-suppress InvalidArgument
+ */
+ public static function handleEnqueueHook($hook)
+ {
+ global $spbc;
+
+ // If the user is not admin
+ if ( ! current_user_can('upload_files')) {
+ return;
+ }
+
+ self::handleAdminWide();
+
+ if ($spbc->settings['upload_checker__file_check'] && in_array($hook, array('upload.php', 'media-new.php'))) {
+ self::getInstance()->js('spbc-upload.js', array('jquery'));
+ }
+
+ // Load UI (modal window) for profile pages
+ if ($hook === 'profile.php' || $hook === 'user-edit.php') {
+ self::handleUserEditPages();
+ }
+
+ // For settings page
+ if ($hook === 'settings_page_spbc') {
+ self::handlePluginSettingsPage();
+ }
+ }
+
+ /**
+ * Enqueue common CSS/JS and localize common data for admin pages.
+ * @return void
+ */
+ private static function handleAdminWide()
+ {
+ global $spbc;
+
+ // For ALL admin pages
+ self::getInstance()->css('spbc-admin.css');
+ self::getInstance()->css('spbc-icons.css');
+ self::getInstance()->js('spbc-common.js', array('jquery'));
+ self::getInstance()->js('spbc-admin.js', array('jquery'));
+
+ $vulnerability_show_install = (
+ isset($spbc->settings['vulnerability_check__test_before_install']) &&
+ $spbc->settings['vulnerability_check__test_before_install'] == true
+ );
+
+ $vulnerability_show_list = (
+ isset($spbc->settings['vulnerability_check__enable_cron'], $spbc->settings['vulnerability_check__warn_on_modules_pages']) &&
+ $spbc->settings['vulnerability_check__enable_cron'] == true &&
+ $spbc->settings['vulnerability_check__warn_on_modules_pages'] == true
+ );
+ wp_localize_script('spbc-common-js', 'spbcSettings', array(
+ 'wpms' => (int) is_multisite(),
+ 'is_main_site' => (int) is_main_site(),
+ 'img_path' => SPBC_PATH . '/images',
+ 'key_is_ok' => $spbc->key_is_ok,
+ 'critical' => $spbc->data['display_scanner_warnings']['critical'],
+ 'secfw_enabled' => $spbc->settings['secfw__enabled'],
+ 'ajax_nonce' => wp_create_nonce("spbc_secret_nonce"),
+ 'ajaxurl' => admin_url('admin-ajax.php', 'relative'),
+ //'debug' => !empty($debug) ? 1 : 0,
+ 'key_changed' => ! empty($spbc->data['key_changed']),
+ 'admin_bar__admins_online_counter' => $spbc->settings['admin_bar__admins_online_counter'] ? 1 : 0,
+ 'needToWhitelist' => ! Cookie::get('spbc_secfw_ip_wl'),
+ 'frontendAnalysisAmount' => (defined('SPBCT_ALLOW_CURL_SINGLE') && SPBCT_ALLOW_CURL_SINGLE) ? 2 : 20,
+ 'spbctNoticeDismissSuccess' => \CleantalkSP\SpbctWP\AdminBannersModule\AdminBannersHandler::getJSONOfPostNotices(),
+ 'vulnerabilityShowInstall' => $vulnerability_show_install,
+ 'vulnerabilityShowList' => $vulnerability_show_list,
+ 'spbcSpinner' => array (
+ 'imgSource' => SPBC_PATH . '/images/preloader2.gif',
+ 'altText' => esc_html__('Loading...', 'security-malware-firewall')
+ ),
+ 'wl_mode_enabled' => $spbc->data['wl_mode_enabled'],
+ 'wl_company_name' => $spbc->data['wl_company_name'],
+ 'wl_support_url' => $spbc->data['wl_support_url'],
+ 'wl_support_email' => $spbc->data['wl_support_email'],
+ 'default_wl_support_url' => $spbc->default_data['wl_support_url'],
+ ));
+
+ self::getInstance()->js('spbc-cookie.js', array('jquery'));
+
+ wp_localize_script(
+ 'spbc-cookie-js',
+ 'spbcPublic',
+ array (
+ '_ajax_nonce' => wp_create_nonce('ct_secret_stuff'),
+ '_rest_nonce' => wp_create_nonce('wp_rest'),
+ '_ajax_url' => admin_url('admin-ajax.php', 'relative'),
+ '_rest_url' => esc_url(get_rest_url()),
+ // '_apbct_ajax_url' => APBCT_URL_PATH . '/lib/Cleantalk/ApbctWP/Ajax.php',
+ 'data__set_cookies' => $spbc->settings['data__set_cookies'],
+ 'data__set_cookies__alt_sessions_type' => $spbc->settings['data__set_cookies__alt_sessions_type'],
+ 'no_confirm_row_actions' => spbc_get_no_confirm_row_actions(),
+ )
+ );
+ }
+
+ /**
+ * Enqueue user data pages scripts. This needs to manage 2fa settings on a user-page.
+ * @return void
+ */
+ private static function handleUserEditPages()
+ {
+ //css only!
+ self::getInstance()->custom(
+ 'jquery-ui',
+ SPBC_PATH . '/css/jquery-ui.min.css',
+ array(),
+ '1.12.1',
+ null,
+ 'all'
+ );
+ wp_enqueue_script('jquery-ui-dialog');
+ }
+
+ /**
+ * Enqueue settings page CSS/JS and localize data for settings page.
+ * @return void
+ */
+ private static function handlePluginSettingsPage()
+ {
+ global $spbc;
+ /**
+ * ============== SETTINGS CSS SCRIPTS ==============
+ */
+ self::getInstance()->css('spbc-settings.css');
+ self::getInstance()->css('spbc-settings-media.css');
+ self::getInstance()->css('spbc-table.css');
+ wp_deregister_style('jquery-ui-style');
+ self::getInstance()->custom(
+ 'jquery-ui',
+ SPBC_PATH . '/css/jquery-ui.min.css',
+ array(),
+ '1.12.1',
+ null,
+ 'all'
+ );
+
+ /**
+ * ============== SETTINGS JS SCRIPTS ==============
+ */
+
+ /**
+ * Load default WordPress scripts or set up our own.
+ */
+ if ( self::jqIsBuiltInVersionApplicable() ) {
+ self::jqAddBuiltIn();
+ } else {
+ self::jqAddCustom();
+ }
+
+ /**
+ * Load custom SPBCT scripts.
+ */
+
+ self::getInstance()->js('spbc-settings.js', array('jquery'), true);
+ self::getInstance()->js('spbc-table.js', array('jquery'), true);
+ self::getInstance()->js('spbc-scanner-plugin.js', array('jquery'), true);
+ self::getInstance()->js('spbc-modal.js', array('jquery'), true);
+ self::getInstance()->js('spbc-react-bundle.js', array('wp-i18n'), ['in_footer']);
+ wp_set_script_translations('spbc-react-bundle-js', 'security-malware-firewall');
+
+ /**
+ * ============== LOCALIZATION FOR JS SCRIPTS ==============
+ */
+
+ /**
+ * Init vars
+ */
+
+ $button_template = '
%s ';
+ $button_template_send = sprintf($button_template, '', 'send', __('Send for analysys', 'security-malware-firewall'));
+ $button_template_delete = sprintf($button_template, '', 'delete', __('Delete', 'security-malware-firewall'));
+ $button_template_approve = sprintf($button_template, '', 'approve', __('Approve', 'security-malware-firewall'));
+ $button_template_view = sprintf($button_template, '', 'view', __('View', 'security-malware-firewall'));
+ $button_template_view_bad = sprintf($button_template, '', 'view_bad', __('View suspicious code', 'security-malware-firewall'));
+ $button_template_replace = sprintf($button_template, '', 'replace', __('Replace with original', 'security-malware-firewall'));
+ $button_template_compare = sprintf($button_template, '', 'compare', __('Show difference', 'security-malware-firewall'));
+ $actions_unknown = $button_template_send . $button_template_delete . $button_template_approve . $button_template_view;
+ $actions_modified = $button_template_approve . $button_template_replace . $button_template_compare . $button_template_view_bad;
+
+ // Getting scanner settings
+ $scanner_settings = array_filter(
+ (array) $spbc->settings,
+ function ($key) {
+ return strpos($key, 'scanner') === 0;
+ },
+ ARRAY_FILTER_USE_KEY
+ );
+
+ /**
+ * Do localize.
+ */
+
+ wp_localize_script('spbc-table-js', 'spbcTableLocalize', array(
+ 'scannerIsActive' => esc_html__('Scanner is active for now. Try later.', 'security-malware-firewall'),
+ ));
+
+ wp_localize_script('spbc-settings-js', 'spbcSettingsSecLogs', array(
+ 'amount' => SPBC_LAST_ACTIONS_TO_VIEW,
+ 'clicks' => 0,
+ ));
+
+ wp_localize_script('spbc-settings-js', 'spbcSettingsFWLogs', array(
+ 'moderate' => $spbc->moderate ? 1 : 0,
+ 'amount' => SPBC_LAST_ACTIONS_TO_VIEW,
+ 'clicks' => 0,
+ ));
+
+ wp_localize_script('spbc-settings-js', 'spbcTable', array(
+ 'warning_bulk' => __('Are sure you want to perform these actions?', 'security-malware-firewall'),
+
+ 'warning_default' => __('Do you want to proceed?', 'security-malware-firewall'),
+
+ 'warning_h_approve' => __('Do you want to approve this file?', 'security-malware-firewall'),
+ 'warning_t_approve' => __('If you agree, this file will be approved.', 'security-malware-firewall'),
+
+ 'warning_h_send' => __('Do you want to proceed?', 'security-malware-firewall'),
+ 'warning_t_send' => __('This file will be sent to the Cloud to analyze for a malware, usually processing takes up to 1 minute. The result will be shown in the Analysis log.', 'security-malware-firewall'),
+
+ 'warning_h_delete' => __('This can\'t be undone and could damage your website. Are you sure?', 'security-malware-firewall'),
+ 'warning_t_delete' => __('If you agree, this file will be deleted.', 'security-malware-firewall'),
+
+ 'warning_h_replace' => __('This can\'t be undone. Are you sure?', 'security-malware-firewall'),
+ 'warning_t_replace' => __('If you agree, this file will be replaced.', 'security-malware-firewall'),
+
+ 'warning_h_quarantine' => __('This could damage your website, but you will have an option to restore the file.', 'security-malware-firewall'),
+ 'warning_t_quarantine' => __('If you agree, this file will be quarantined.', 'security-malware-firewall'),
+ ));
+
+ wp_localize_script('spbc-settings-js', 'spbcScaner', array(
+
+ // PARAMS
+ 'settings' => $scanner_settings,
+ 'states' => ScannerQueue::$stages,
+ 'timezone_shift' => $spbc->data['site_utc_offset_in_seconds'] ?: false,
+
+ // Settings / Statuses
+ 'scaner_enabled' => $spbc->scaner_enabled ? 1 : 0,
+ 'check_links' => $spbc->settings['scanner__outbound_links'] ? 1 : 0,
+ 'check_heuristic' => $spbc->settings['scanner__heuristic_analysis'] ? 1 : 0,
+ 'check_signature' => $spbc->settings['scanner__signature_analysis'] ? 1 : 0,
+ 'auto_cure' => $spbc->settings['scanner__auto_cure'] ? 1 : 0,
+ 'check_frontend' => $spbc->settings['scanner__frontend_analysis'] ? 1 : 0,
+ 'check_listing' => $spbc->settings['scanner__important_files_listing'] ? 1 : 0,
+ 'wp_content_dir' => realpath(WP_CONTENT_DIR),
+ 'wp_root_dir' => realpath(ABSPATH),
+
+ // Templates
+ 'row_template' => '
%s %s %s %s %s ',
+ 'row_template_links' => '
%s %s %s ',
+ 'actions_unknown' => $actions_unknown,
+ 'actions_modified' => $actions_modified,
+ 'page_selector_template' => '',
+
+ //TRANSLATIONS
+
+ //Confirmation
+ 'scan_modified_confiramation' => __('There is more than 30 modified files and this could take time. Do you want to proceed?', 'security-malware-firewall'),
+ 'warning_about_cancel' => __('Scan will be performed in the background mode soon.', 'security-malware-firewall'),
+ 'delete_warning' => __('Are you sure you want to delete the file? It can not be undone.'),
+ // Buttons
+ 'button_scan_perform' => __('Perform Scan', 'security-malware-firewall'),
+ 'button_scan_pause' => __('Pause scan', 'security-malware-firewall'),
+ 'button_scan_resume' => __('Resume scan', 'security-malware-firewall'),
+ // Progress bar
+ 'progressbar_get_cms_hashes' => __('Receiving hashes', 'security-malware-firewall'),
+ 'progressbar_get_modules_hashes' => __('Receiving plugins hashes', 'security-malware-firewall'),
+ 'progressbar_get_approved_hashes' => __('Updating statuses for the approved files', 'security-malware-firewall'),
+ 'progressbar_get_denied_hashes' => __('Updating statuses for the denied files', 'security-malware-firewall'),
+ 'progressbar_clean_results' => __('Preparing', 'security-malware-firewall'),
+ // Scanning core
+ 'progressbar_file_system_analysis' => __('Scanning for modifications', 'security-malware-firewall'),
+ 'progressbar_heuristic_analysis' => __('Heuristic analysis', 'security-malware-firewall'),
+ 'progressbar_schedule_send_heuristic_suspicious_files' => __('Schedule suspicious files to be automatically sent for analysis', 'security-malware-firewall'),
+ 'progressbar_signature_analysis' => __('Searching for signatures', 'security-malware-firewall'),
+ //Cure
+ 'progressbar_auto_cure_backup' => __('Creating a backup', 'security-malware-firewall'),
+ 'progressbar_auto_cure' => __('Cure', 'security-malware-firewall'),
+ // Links
+ 'progressbar_outbound_links' => __('Scanning links', 'security-malware-firewall'),
+ // Frontend
+ 'progressbar_frontend_analysis' => __('Scanning pages', 'security-malware-firewall'),
+ // Other
+ 'progressbar_important_files_listing' => __('Check pages for listing', 'security-malware-firewall'),
+ 'progressbar_send_results' => __('Sending results', 'security-malware-firewall'),
+ // Warnings
+ 'result_text_bad_template' => __('Recommend to scan all (%s) of the found files to make sure the website is secure.', 'security-malware-firewall'),
+ 'result_text_good_template' => __('No threats are found.', 'security-malware-firewall'),
+ //Misc
+ 'look_below_for_scan_res' => __('Look below for scan results.', 'security-malware-firewall'),
+ 'view_all_results' => sprintf(
+ __('%sView all scan results for this website%s', 'security-malware-firewall'),
+ '
',
+ ' '
+ ),
+ 'last_scan_was_just_now' => __('The last scan of this website happened just now. Files scanned: %s.', 'security-malware-firewall'),
+ 'last_scan_was_just_now_links' => __('The last scan of this website happened just now. Files scanned: %s. Outbound links found: %s.', 'security-malware-firewall'),
+ 'copy_log_to_clipboard_hint' => __('Copied!', 'security-malware-firewall'),
+ 'copy_log_to_clipboard_hint_failed' => __('Failed to copy!', 'security-malware-firewall'),
+ 'copy_log_to_clipboard_hint_unsupported' => __('Clipboard API not supported in local environment', 'security-malware-firewall'),
+ ));
+
+ wp_localize_script('spbc-settings-js', 'spbcDescriptions', array(
+ 'waf__enabled' => __('Bla bla', 'security-malware-firewall'),
+ 'waf__xss_check' => __('Cross-Site Scripting (XSS) — prevents malicious code to be executed/sent to any user. As a result malicious scripts can not get access to the cookie files, session tokens and any other confidential information browsers use and store. Such scripts can even overwrite content of HTML pages. CleanTalk WAF monitors for patterns of these parameters and block them.', 'security-malware-firewall'),
+ 'waf__sql_check' => __('SQL Injection — one of the most popular ways to hack websites and programs that work with databases. It is based on injection of a custom SQL code into database queries. It could transmit data through GET, POST requests or cookie files in an SQL code. If a website is vulnerable and execute such injections then it would allow attackers to apply changes to the website\'s MySQL database.', 'security-malware-firewall'),
+ 'upload_checker__file_check' => __('The option checks each uploaded file to a website for malicious code. If it\'s possible for visitors to upload files to a website, for instance a work resume, then attackers could abuse it and upload an infected file to execute it later and get access to your website.', 'security-malware-firewall'),
+ 'traffic_control__enabled' => __('It analyzes quantity of requests towards website from any IP address for a certain period of time. For example, for an ordinary visitor it\'s impossible to generate 2000 requests within 1 hour. Big amount of requests towards website from the same IP address indicates that there is a high chance of presence of a malicious program.', 'security-malware-firewall'),
+ 'scanner__outbound_links' => __('This option allows you to know the number of outgoing links on your website and website addresses they lead to. The option\'s purpose is to check your website and find hidden, forgotten and spam links. You should always remember if you have links to other websites which have a bad reputation, it could affect your visitors\' trust and your SEO.', 'security-malware-firewall'),
+ 'scanner__heuristic_analysis' => __('Often, authors of malicious code disguise their code which makes it difficult to identify it by their signatures. The malicious code itself can be placed anywhere on the site, for example the obfuscated PHP-code in the "logo.png" file, and the code itself is called by one inconspicuous line in "index.php". Therefore, the usage of plugins to search for malicious code is preferable. Heuristic analysis can indicate suspicious PHP constructions in a file that you should pay attention to.', 'security-malware-firewall'),
+ 'scanner__signature_analysis' => __('Code signatures — it\'s a code sequence a malicious program consists of. Signatures are being added to the database after analysis of the infected files. Search for such malicious code sequences is performed in scanning by signatures. If any part of code matches a virus code from the database, such files would be marked as critical.', 'security-malware-firewall'),
+ 'scanner__auto_cure' => __('It cures infected files automatically if the scanner knows cure methods for these specific cases. If the option is disabled then when the scanning process ends you will be presented with several actions you can do to the found files: Cure. Malicious code will be removed from the file. Replace. The file will be replaced with the original file. Delete. The file will be put in quarantine. Do nothing. Before any action is chosen, backups of the files will be created and if the cure is unsuccessful it\'s possible to restore each file.', 'security-malware-firewall'),
+ 'misc__backend_logs_enable' => __('To control appearing errors you have to check log file of your hosting account regularly. It\'s inconvenient and just a few webmasters pay attention to it. Also, errors could appear for a short period of time and only when one specific function is running, they can\'t be spotted in other circumstances so it\'s hard to catch them. PHP errors tell you that some of your website functionality doesn\'t work correctly, furthermore hackers may use these errors to get access to your website. The CleanTalk Scanner will check your website backend once per hour. Statistics of errors is available in your CleanTalk Dashboard.', 'security-malware-firewall'),
+ 'data__set_cookies' => __('Part of the CleanTalk FireWall functions depend on cookie files, so disabling this option could lead to deceleration of the firewall work. It will affect user identification who are logged in right now. Traffic Control will not be able to determine authorized users and they could be blocked when the request limit is reached. We do not recommend to disable this option without serious reasons. However, you should disable this option is you\'re using Varnish.', 'security-malware-firewall'),
+ '2fa__enable' => __('Two-Factor Authentication for WordPress admin accounts will improve your website security and make it safer, if not impossible, for hackers to breach your WordPress account. Two-Factor Authentication works via e-mail. Authentication code will be sent to your admin email. When authorizing, a one-time code will be sent to your email. While entering the code, make sure that it does not contain spaces. With your first authorization, the CleanTalk Security plugin remembers your browser and you won’t have to input your authorization code every time anymore. However, if you started to use a new device or a new browser then you are required to input your authorization code. The plugin will remember your browser for 30 days.', 'security-malware-firewall'),
+ ));
+ }
+
+ /**
+ * Handle script tags with some attributes (ex. defer/async)
+ * @param string $tag
+ * @param string $handle
+ *
+ * @psalm-suppress PossiblyUnusedReturnValue
+ * @return string
+ */
+ public static function addScriptAttributes($tag, $handle)
+ {
+ $async_scripts = array(
+ 'spbc-scannerplugin-js',
+ 'spbc-scaner-events-js',
+ 'spbc-scaner-callbacks-js',
+ );
+
+ $defer_scripts = array(
+ 'spbc-settings-js',
+ 'spbc-scaner-js',
+ );
+
+ if (in_array($handle, $async_scripts)) {
+ return str_replace(' src', ' async="async" src', $tag);
+ } elseif (in_array($handle, $defer_scripts)) {
+ return str_replace(' src', ' defer="defer" src', $tag);
+ } else {
+ return $tag;
+ }
+ }
+
+ /**
+ * Enqueue built in jQuery source from WordPress src
+ * @return void
+ */
+ private static function jqAddBuiltIn()
+ {
+ wp_enqueue_script('jquery-ui-core');
+ wp_enqueue_script('jquery-ui-progressbar');
+ wp_enqueue_script('jquery-ui-accordion');
+ wp_enqueue_script('jquery-ui-resizable');
+ wp_enqueue_script('jquery-ui-dialog');
+ }
+
+ /**
+ * Enqueue custom jQuery lib from ./js/lib
+ * @return void
+ */
+ private static function jqAddCustom()
+ {
+ self::getInstance()->custom(
+ 'jquery-ui',
+ SPBC_PATH . '/js/lib/jquery/jquery-ui.min.js',
+ array('jquery'),
+ '1.13.3',
+ true,
+ null
+ );
+ }
+
+ /**
+ * Checks if built in version of JQuery is applicable for plugin.
+ * @return bool
+ */
+ private static function jqIsBuiltInVersionApplicable()
+ {
+ global $wp_version;
+ try {
+ if (empty($wp_version)) {
+ return false;
+ }
+ // Enqueue so we can grab the built-in version
+ wp_enqueue_script('jquery');
+
+ // Get jquery handle - WP 3.6 or newer changed the jQuery handle (once we're on 3.6+ we can remove this logic)
+ $jquery_handle = (version_compare($wp_version, '3.6-alpha1', '>=') ) ? 'jquery-core' : 'jquery';
+
+ // Get the WP built-in version
+ $wp_jquery_ver = isset($GLOBALS['wp_scripts']->registered['$jquery_handle'])
+ ? $GLOBALS['wp_scripts']->registered[$jquery_handle]->ver
+ : false;
+
+ // applicable version is 3.6.3+
+ return !empty($wp_jquery_ver) && version_compare($wp_jquery_ver, '3.6.3', '>=');
+ } catch (\Exception $e) {
+ return false;
+ }
+ }
}
diff --git a/lib/CleantalkSP/SpbctWP/Variables/AltSessions.php b/lib/CleantalkSP/SpbctWP/Variables/AltSessions.php
index ddc0e1387..4a9c09dee 100644
--- a/lib/CleantalkSP/SpbctWP/Variables/AltSessions.php
+++ b/lib/CleantalkSP/SpbctWP/Variables/AltSessions.php
@@ -22,8 +22,8 @@ class AltSessions
public static function getID()
{
$id = Ip::get('real')
- . Server::get('HTTP_USER_AGENT')
- . Server::get('HTTP_ACCEPT_LANGUAGE');
+ . Server::getString('HTTP_USER_AGENT')
+ . Server::getString('HTTP_ACCEPT_LANGUAGE');
return hash('sha256', $id);
}
@@ -78,7 +78,7 @@ public static function set($name, $value)
public static function setFromRemote($request = null)
{
if ( ! $request ) {
- $cookies_to_set = (array)\CleantalkSP\Variables\Post::get('cookies');
+ $cookies_to_set = (array)\CleantalkSP\Variables\Post::getString('cookies'); // validation is done next line
} else {
$cookies_to_set = $request->get_param('cookies');
}
@@ -127,7 +127,7 @@ public static function getFromRemote($request = null)
$value = Cookie::get(
$request
? $request->get_param('cookies')
- : \CleantalkSP\Variables\Post::get('name')
+ : \CleantalkSP\Variables\Post::getString('name')
);
wp_send_json(array('success' => true, 'value' => $value));
diff --git a/lib/CleantalkSP/SpbctWP/Variables/Cookie.php b/lib/CleantalkSP/SpbctWP/Variables/Cookie.php
index b78bd26f7..2829be7f9 100644
--- a/lib/CleantalkSP/SpbctWP/Variables/Cookie.php
+++ b/lib/CleantalkSP/SpbctWP/Variables/Cookie.php
@@ -75,7 +75,7 @@ public static function set(
) {
global $spbc;
- $secure = ! is_null($secure) ? $secure : Server::get('HTTPS') || Server::get('SERVER_PORT') == 443;
+ $secure = ! is_null($secure) ? $secure : Server::getString('HTTPS') || Server::getInt('SERVER_PORT') == 443;
// Convert to JSON if array or object
if ( ! is_scalar($value) ) {
diff --git a/lib/CleantalkSP/Variables/Cookie.php b/lib/CleantalkSP/Variables/Cookie.php
index 3fbb77d46..f62f0da2e 100644
--- a/lib/CleantalkSP/Variables/Cookie.php
+++ b/lib/CleantalkSP/Variables/Cookie.php
@@ -55,7 +55,7 @@ protected function getVariable($name, $do_decode = true)
public static function set($name, $value = '', $expires = 0, $path = '', $domain = '', $secure = null, $httponly = false, $samesite = 'Lax')
{
- $secure = ! is_null($secure) ? $secure : Server::get('HTTPS') !== 'off' || Server::get('SERVER_PORT') == 443;
+ $secure = ! is_null($secure) ? $secure : Server::getString('HTTPS') !== 'off' || Server::getInt('SERVER_PORT') == 443;
// For PHP 7.3+ and above
if ( version_compare(phpversion(), '7.3.0', '>=') ) {
diff --git a/lib/CleantalkSP/Variables/ServerVariables.php b/lib/CleantalkSP/Variables/ServerVariables.php
index bc980e096..fe3be73f2 100644
--- a/lib/CleantalkSP/Variables/ServerVariables.php
+++ b/lib/CleantalkSP/Variables/ServerVariables.php
@@ -2,6 +2,7 @@
namespace CleantalkSP\Variables;
+use CleantalkSP\Common\TT;
use CleantalkSP\SpbctWP\Sanitize;
use CleantalkSP\SpbctWP\Validate;
use CleantalkSP\Templates\Singleton;
@@ -70,6 +71,75 @@ public static function get($name, $validation_filter = null, $sanitize_filter =
return $variable;
}
+ /**
+ * @param $var_name
+ * @param $default
+ * @param $validation_filter
+ * @param $sanitize_filter
+ *
+ * @return string
+ */
+ public static function getString($var_name, $default = '', $validation_filter = null, $sanitize_filter = null)
+ {
+ return TT::toString(
+ static::get(
+ $var_name,
+ $validation_filter,
+ $sanitize_filter
+ ),
+ $default
+ );
+ }
+
+ /**
+ * @param $var_name
+ * @param $default
+ *
+ * @return int
+ */
+ public static function getInt($var_name, $default = 0)
+ {
+ return TT::toInt(
+ static::get(
+ $var_name
+ ),
+ $default
+ );
+ }
+
+ /**
+ * @param $var_name
+ * @param $default
+ *
+ * @return bool
+ */
+ public static function getBool($var_name, $default = false)
+ {
+ return TT::toBool(
+ static::get(
+ $var_name
+ ),
+ $default
+ );
+ }
+
+ /**
+ * @param $var_name
+ * @param $default
+ *
+ * @return array
+ * @psalm-suppress PossiblyUnusedMethod
+ */
+ public static function getArray($var_name, $default = array())
+ {
+ return TT::toArray(
+ static::get(
+ $var_name
+ ),
+ $default
+ );
+ }
+
/**
* Save variable to $this->variables[]
*
diff --git a/readme.txt b/readme.txt
index cc4abca12..93d6a1092 100644
--- a/readme.txt
+++ b/readme.txt
@@ -2,9 +2,9 @@
Contributors: glomberg, alexandergull, sergefcleantalk
Tags: security, firewall, malware, wordpress security, brute force
Requires at least: 5.0
-Tested up to: 6.7
+Tested up to: 6.8
Requires PHP: 5.6
-Stable tag: 2.154
+Stable tag: 2.155
License: GPLv2
License URI: https://www.gnu.org/licenses/gpl-2.0.html
@@ -339,6 +339,23 @@ This is required for the Security FireWall to function properly. Plugins that ar
== Changelog ==
+= 2.155 Apr 21 2025
+* New. Scanner. Heuristic. Entropy analysis updated to find suspicious array key calls.
+* Fix. SettingsPage. Textdomain fix
+* Fix. HTTP. Get DNS records. False result handled.
+* Ref. Admin page. CSS styles and JS scripts enqueuing refactored.
+* Upd. Admin. jQuery lib automatic dependency implemented (built-in/cutom setup).
+* Fix. Scanner. Heuristic. Entropy. Variables. WeakSpots reduction fixed.
+* Ref. Code. Update validation.
+* Fix. Settings. Block API-key layout fixed.
+* Fix. Surface. Skip symlinks.
+* Fix. Scanner. Heuristic. Entropy. Array keys detection fixed.
+* Fix. Scan. Skip directories we can't access.
+* Fix. Scan. Implement error handling and filter management for themes_api calls.
+* Fix. DB. Improved compatibility with mysql.
+* Fix. WL Mode. WL entities updated on whole project.
+* Fix. Code. Deprecated notices about FILTER_SANITIZE_STRING fixed.
+
= 2.154 Mar 25 2025
* Upd. Settings. Improved FW test block page.
* Upd. Settings. Improved 2fa handler.
diff --git a/security-malware-firewall.php b/security-malware-firewall.php
index 3f625436a..d758c7c93 100644
--- a/security-malware-firewall.php
+++ b/security-malware-firewall.php
@@ -5,7 +5,7 @@
Plugin URI: https://wordpress.org/plugins/security-malware-firewall/
Description: Security & Malware scan by CleanTalk to protect your website from online threats and viruses. IP/Country FireWall, Web application FireWall. Detailed stats and logs to have full control.
Author: CleanTalk Security
-Version: 2.154
+Version: 2.155
Author URI: https://cleantalk.org
Text Domain: security-malware-firewall
Domain Path: /i18n
@@ -180,7 +180,7 @@
if ( SpbcRemoteCalls::check() ) {
try {
- if ( Get::get('spbc_remote_call_action') === 'run_service_template_get' ) {
+ if ( Get::getString('spbc_remote_call_action') === 'run_service_template_get' ) {
require_once(SPBC_PLUGIN_DIR . 'inc/spbc-settings.php');
}
$rc = new SpbcRemoteCalls($spbc);
@@ -331,7 +331,7 @@ function spbc_change_author_name($link, $_author_id, $_author_nicename)
//Password-protected pages also uses wp-login page, we should not break it
if ( $spbc->settings['login_page_rename__enabled'] ) {
- if ( Get::get('action') === 'postpass' ) {
+ if ( Get::getString('action') === 'postpass' ) {
require ABSPATH . 'wp-includes/pluggable.php';
require ABSPATH . 'wp-login.php';
}
@@ -371,20 +371,19 @@ function spbc_change_author_name($link, $_author_id, $_author_nicename)
unset($spbc_cron);
if ( is_admin() || is_network_admin() ) {
- // Async loading for JavaScript
- add_filter('script_loader_tag', 'spbc_admin_add_script_attribute', 10, 3);
-
include_once SPBC_PLUGIN_DIR . 'inc/spbc-admin.php';
include_once SPBC_PLUGIN_DIR . 'templates/spbc_settings_main.php'; // Templates for settings pgae
+ // Async loading for JavaScript
+ add_filter('script_loader_tag', array('CleantalkSP\SpbctWP\SpbcEnqueue', 'addScriptAttributes'), 10, 3);
add_action('admin_init', array('CleantalkSP\SpbctWP\Activator', 'redirectAfterActivation'), 1); // Redirect after activation
add_action('admin_init', 'spbc_admin_init', 1, 1); // Main admin hook
add_action('admin_menu', 'spbc_admin_add_page'); // Admin pages
add_action('network_admin_menu', 'spbc_admin_add_page'); // Network admin pages
- add_action('admin_enqueue_scripts', 'spbc_enqueue_scripts'); // Scripts
+ add_action('admin_enqueue_scripts', array('CleantalkSP\SpbctWP\SpbcEnqueue', 'handleEnqueueHook')); // Scripts
// Getting dashboard widget statistics by click
- if ( (int) Post::get('spbc_brief_refresh') === 1 ) {
+ if (Post::getInt('spbc_brief_refresh') === 1 ) {
spbc_set_brief_data();
}
@@ -442,14 +441,14 @@ function spbc_set_headers()
spbc_is_user_logged_in() &&
! empty($spbc->settings['data__set_cookies']) &&
(
- ! Cookie::get('spbc_is_logged_in') ||
- Cookie::get('spbc_is_logged_in') !== md5($spbc->data['salt'] . get_option('home'))
+ ! Cookie::getString('spbc_is_logged_in') ||
+ Cookie::getString('spbc_is_logged_in') !== md5($spbc->data['salt'] . get_option('home'))
)
) {
// skip rewriting spbc_is_logged_in cookie on favicon request for WPMS - its always run on main site url and returns it`s home url
if (
is_multisite() &&
- strpos(Server::get('REQUEST_URI'), 'favicon.ico') !== false
+ strpos(Server::get('REQUEST_URI', null, 'url'), 'favicon.ico') !== false
) {
return;
}
@@ -579,7 +578,7 @@ function spbc_authenticate__check_brute_force()
'api_key' => $spbc->api_key,
'state' => $spbc,
'is_login_page' => strpos(trim(Server::getURL(), '/'), trim($login_url, '/')) === 0,
- 'is_logged_in' => Cookie::get('spbc_is_logged_in') === md5($spbc->data['salt'] . get_option('home')),
+ 'is_logged_in' => Cookie::getString('spbc_is_logged_in') === md5($spbc->data['salt'] . get_option('home')),
'bf_limit' => $spbc->settings['bfp__allowed_wrong_auths'],
'block_period' => $spbc->settings['bfp__block_period__5_fails'],
'count_period' => $spbc->settings['bfp__count_interval'],
@@ -756,7 +755,7 @@ function spbct_sfw_private_records_handler($action, $test_data = null)
$error = 'secfw_private_records_handler: ';
if ( !empty($action) && (in_array($action, array('add', 'delete'))) ) {
- $metadata = !empty($test_data) ? $test_data : Post::get('metadata');
+ $metadata = !empty($test_data) ? $test_data : Post::getString('metadata'); // validation is done next line
/**
* Validate JSON
@@ -914,8 +913,8 @@ function spbc_user_is_admin()
if (!empty($spbc->settings['data__set_cookies'])) {
return
- Cookie::get('spbc_is_logged_in') === md5($spbc->data['salt'] . get_option('home')) &&
- Cookie::get('spbc_admin_logged_in') === md5($spbc->data['salt'] . 'admin' . get_option('home'));
+ Cookie::getString('spbc_is_logged_in') === md5($spbc->data['salt'] . get_option('home')) &&
+ Cookie::getString('spbc_admin_logged_in') === md5($spbc->data['salt'] . 'admin' . get_option('home'));
}
return is_admin();
@@ -1086,7 +1085,7 @@ function spbc_set_api_key()
$platform = 'wordpress';
$user_ip = IP::get();
$timezone = (string)get_option('gmt_offset');
- $language = Server::get('HTTP_ACCEPT_LANGUAGE');
+ $language = Server::getString('HTTP_ACCEPT_LANGUAGE');
$is_wpms = is_multisite() && defined('SUBDOMAIN_INSTALL') && ! SUBDOMAIN_INSTALL;
$white_label = false;
$hoster_api_key = $spbc->ms__hoster_api_key;
@@ -1712,7 +1711,7 @@ function spbc_private_list_add()
$ip = IP::get();
- if ( Cookie::get('spbc_secfw_ip_wl') === md5($ip . $spbc->spbc_key) ) {
+ if ( Cookie::getString('spbc_secfw_ip_wl') === md5($ip . $spbc->spbc_key) ) {
return;
}