From e0df885fb2da483dd2eca77a8d441db36558c94a Mon Sep 17 00:00:00 2001 From: alexandergull Date: Wed, 5 Jun 2024 16:21:13 +0500 Subject: [PATCH 1/7] New. PHPCodeValidator class. Validate code before heuristic check start. --- js/spbc-table.min.js.map | 2 +- .../HeuristicAnalyser/HeuristicAnalyser.php | 17 +- .../HeuristicAnalyser/Modules/CodeStyle.php | 26 --- .../Modules/PHPCodeValidator.php | 165 ++++++++++++++++++ .../HeuristicAnalyser/Modules/Tokens.php | 47 +++++ 5 files changed, 228 insertions(+), 29 deletions(-) create mode 100644 lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/PHPCodeValidator.php diff --git a/js/spbc-table.min.js.map b/js/spbc-table.min.js.map index e17165ef0..fb57994b7 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;\n\n/**\n * Reloads scanner accordion and set all the listeners\n */\nfunction spbcReloadAccordion() {\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 },\n },\n jQuery('#spbc_scan_accordion'),\n );\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 ];\n let action = self.siblings('select').children()[self.siblings('select').first()[0].selectedIndex].value;\n\n if ( allowedBulkActions.indexOf( action ) !== -1 ) {\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 const selectedItems = self.closest('#spbc_tbl__scanner_cure_log').find('.cb-select');\n let selectedIds = [];\n\n selectedItems.each(function(index, element) {\n const elementId = jQuery(element).val();\n selectedIds.push(elementId);\n });\n data.selectedIds = selectedIds;\n }\n\n if (action === 'delete_from_analysis_log') {\n const selectedItems = self.closest('#spbc_tbl__scanner_analysis_log').find('.cb-select');\n let fileIds = [];\n\n selectedItems.each(function(index, element) {\n const elementId = jQuery(element).val();\n fileIds.push(elementId);\n });\n data.file_ids = fileIds;\n }\n\n let params = {\n button: this,\n spinner: self.children('.tbl-preloader--small'),\n callback: function(out) {\n spbcReloadAccordion();\n if ( action === 'check_analysis_status' && typeof out !== 'undefined') {\n let html = '

Analysis status updated.' +\n ' Total: ' + out.counters.total +\n ', updated: ' + out.counters.updated +\n ', skipped: ' + out.counters.skipped +\n ', failed: ' + out.counters.failed +\n ', queued: ' + out.counters.queued +\n '

';\n spbcModal.open().put( html );\n }\n if ( action === 'send' && typeof out !== 'undefined') {\n let html = '

Files have been sent: ' +\n out.files_sent_counter +\n '

';\n spbcModal.open().put(html);\n }\n },\n errorOutput: function( errorText, comment ) {\n if ( comment ) {\n errorText = errorText + '
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 if (!spbcBulkAction && !confirm(spbcTable.warning_bulk)) {\n return;\n }\n\n let self = spbcBulkAction || jQuery(this);\n spbcBulkAction = self;\n let action = self.siblings('select').children()[self.siblings('select').first()[0].selectedIndex].value;\n\n if (action === 'cure') {\n spbcScannerCureSelected(jQuery(this));\n return;\n }\n\n if (action === 'delete_from_analysis_log') {\n spbc_scanner_analysis_log_delete_from_log(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 spbc_sec_logs__filter_ip(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 });\n}\n\n/**\n * Cure selected files\n * @param {obj} current\n */\nfunction spbcScannerCureSelected(current) {\n const selectedItems = current.closest('#spbc_tbl__scanner_cure_log').find('.cb-select:checked');\n let selectedIds = [];\n\n if (selectedItems.length === 0) {\n alert('Please, select elements.');\n }\n\n selectedItems.each(function(index, element) {\n const elementId = jQuery(element).val();\n selectedIds.push(elementId);\n });\n\n const data = {\n action: 'spbc_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 if (result.success) {\n spbcModal.open().put(result.data);\n document.addEventListener('spbcModalClosed', function( e ) {\n document.location.reload();\n });\n } else {\n spbcModal.open().putError(result.data);\n }\n },\n });\n}\n\n/**\n * Table row actions\n */\nfunction spbcTblRowActionsListen() {\n jQuery('.tbl-row_action--ajax')\n .off('click')\n .on('click', function() {\n console.log('spbcTblRowActionsListen click');\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) {\n spbcModal.open().putError( msg );\n },\n spinner: self.parent().siblings('.tbl-preloader--tiny'),\n };\n if (!spbcBulkAction) {\n //console.log(self.parent().parent()[0].firstChild.innerHTML);\n let fileName = self.parent().parent()[0].firstChild.innerHTML;\n let confirmation = spbcTable['warning_'+self.attr('row-action')] || spbcTable.warning_default;\n // Without confirm\n if (\n data.add_action === 'copy_file_info' ||\n data.add_action === 'check_analysis_status'\n ) {\n spbcSendAJAXRequest(data, params, self.parents('tr'));\n\n // With confirm\n } else {\n spbcModal.open().confirm(confirmation, fileName, (confirmed) => {\n if (confirmed) {\n spbcSendAJAXRequest(data, params, self.parents('tr'));\n }\n });\n }\n }\n if (spbcBulkAction) {\n spbcSendAJAXRequest(data, params, self.parents('tr'));\n }\n });\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 = '

Analysis Log (' + countRowInTemplate + ')

';\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});\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"],"names":["let","spbcBulkAction","spbcReloadAccordion","spbcSendAJAXRequest","action","notJson","callback","result","data","params","obj","jQuery","accordion","html","header","heightStyle","collapsible","active","spbcTblBulkActionsListen","spbcTblRowActionsListen","spbcTblPaginationListen","spbcTblSortListen","spbcStartShowHide","off","on","spbcScanner","alert","spbcTableLocalize","scannerIsActive","self","this","siblings","children","first","selectedIndex","value","indexOf","confirm","spbcTable","warning_bulk","add_action","status","parents","attr","selectedItems","closest","find","selectedIds","each","index","element","elementId","val","push","fileIds","file_ids","button","spinner","out","counters","total","updated","skipped","failed","queued","spbcModal","open","put","files_sent_counter","errorOutput","errorText","comment","putError","timeout","e","spbcScannerCureSelected","spbc_scanner_analysis_log_delete_from_log","sendAction","items","msg","show","ip","spbc_sec_logs__filter_ip","prop","hide","setTimeout","is","click","current","length","security","spbcSettings","ajax_nonce","ajax","type","url","ajaxurl","beforeSend","success","document","addEventListener","location","reload","console","log","id","cols","page_url","parent","page_id","spbcTblRowActionsCallback","fileName","confirmation","firstChild","innerHTML","warning_default","confirmed","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","append","tabHeaderTemplate","tabBodyTemplate","after","spbcTblPaginationCallback","page","removeAttr","spbcTblSortCallback","domain","target","classList","contains","order_by","order","spbcScannerSwitchTable","_obj","spbcShowHideRows","blockId","columnKey","block","hasClass","removeClass","addClass","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;\n\n/**\n * Reloads scanner accordion and set all the listeners\n */\nfunction spbcReloadAccordion() {\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 },\n },\n jQuery('#spbc_scan_accordion'),\n );\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 ];\n let action = self.siblings('select').children()[self.siblings('select').first()[0].selectedIndex].value;\n\n if ( allowedBulkActions.indexOf( action ) !== -1 ) {\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 const selectedItems = self.closest('#spbc_tbl__scanner_cure_log').find('.cb-select');\n let selectedIds = [];\n\n selectedItems.each(function(index, element) {\n const elementId = jQuery(element).val();\n selectedIds.push(elementId);\n });\n data.selectedIds = selectedIds;\n }\n\n if (action === 'delete_from_analysis_log') {\n const selectedItems = self.closest('#spbc_tbl__scanner_analysis_log').find('.cb-select');\n let fileIds = [];\n\n selectedItems.each(function(index, element) {\n const elementId = jQuery(element).val();\n fileIds.push(elementId);\n });\n data.file_ids = fileIds;\n }\n\n let params = {\n button: this,\n spinner: self.children('.tbl-preloader--small'),\n callback: function(out) {\n spbcReloadAccordion();\n if ( action === 'check_analysis_status' && typeof out !== 'undefined') {\n let html = '

Analysis status updated.' +\n ' Total: ' + out.counters.total +\n ', updated: ' + out.counters.updated +\n ', skipped: ' + out.counters.skipped +\n ', failed: ' + out.counters.failed +\n ', queued: ' + out.counters.queued +\n '

';\n spbcModal.open().put( html );\n }\n if ( action === 'send' && typeof out !== 'undefined') {\n let html = '

Files have been sent: ' +\n out.files_sent_counter +\n '

';\n spbcModal.open().put(html);\n }\n },\n errorOutput: function( errorText, comment ) {\n if ( comment ) {\n errorText = errorText + '
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 if (!spbcBulkAction && !confirm(spbcTable.warning_bulk)) {\n return;\n }\n\n let self = spbcBulkAction || jQuery(this);\n spbcBulkAction = self;\n let action = self.siblings('select').children()[self.siblings('select').first()[0].selectedIndex].value;\n\n if (action === 'cure') {\n spbcScannerCureSelected(jQuery(this));\n return;\n }\n\n if (action === 'delete_from_analysis_log') {\n spbc_scanner_analysis_log_delete_from_log(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 spbc_sec_logs__filter_ip(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 });\n}\n\n/**\n * Cure selected files\n * @param {obj} current\n */\nfunction spbcScannerCureSelected(current) {\n const selectedItems = current.closest('#spbc_tbl__scanner_cure_log').find('.cb-select:checked');\n let selectedIds = [];\n\n if (selectedItems.length === 0) {\n alert('Please, select elements.');\n }\n\n selectedItems.each(function(index, element) {\n const elementId = jQuery(element).val();\n selectedIds.push(elementId);\n });\n\n const data = {\n action: 'spbc_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 if (result.success) {\n spbcModal.open().put(result.data);\n document.addEventListener('spbcModalClosed', function( e ) {\n document.location.reload();\n });\n } else {\n spbcModal.open().putError(result.data);\n }\n },\n });\n}\n\n/**\n * Table row actions\n */\nfunction spbcTblRowActionsListen() {\n jQuery('.tbl-row_action--ajax')\n .off('click')\n .on('click', function() {\n console.log('spbcTblRowActionsListen click');\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) {\n spbcModal.open().putError( msg );\n },\n spinner: self.parent().siblings('.tbl-preloader--tiny'),\n };\n if (!spbcBulkAction) {\n let fileName = self.parent().parent()[0].firstChild.innerHTML;\n let confirmation = spbcTable['warning_'+self.attr('row-action')] || spbcTable.warning_default;\n // Without confirm\n if (\n data.add_action === 'copy_file_info' ||\n data.add_action === 'check_analysis_status'\n ) {\n spbcSendAJAXRequest(data, params, self.parents('tr'));\n\n // With confirm\n } else {\n spbcModal.open().confirm(confirmation, fileName, (confirmed) => {\n if (confirmed) {\n spbcSendAJAXRequest(data, params, self.parents('tr'));\n }\n });\n }\n }\n if (spbcBulkAction) {\n spbcSendAJAXRequest(data, params, self.parents('tr'));\n }\n });\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 = '

Analysis Log (' + countRowInTemplate + ')

';\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});\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"],"names":["let","spbcBulkAction","spbcReloadAccordion","spbcSendAJAXRequest","action","notJson","callback","result","data","params","obj","jQuery","accordion","html","header","heightStyle","collapsible","active","spbcTblBulkActionsListen","spbcTblRowActionsListen","spbcTblPaginationListen","spbcTblSortListen","spbcStartShowHide","off","on","spbcScanner","alert","spbcTableLocalize","scannerIsActive","self","this","siblings","children","first","selectedIndex","value","indexOf","confirm","spbcTable","warning_bulk","add_action","status","parents","attr","selectedItems","closest","find","selectedIds","each","index","element","elementId","val","push","fileIds","file_ids","button","spinner","out","counters","total","updated","skipped","failed","queued","spbcModal","open","put","files_sent_counter","errorOutput","errorText","comment","putError","timeout","e","spbcScannerCureSelected","spbc_scanner_analysis_log_delete_from_log","sendAction","items","msg","show","ip","spbc_sec_logs__filter_ip","prop","hide","setTimeout","is","click","current","length","security","spbcSettings","ajax_nonce","ajax","type","url","ajaxurl","beforeSend","success","document","addEventListener","location","reload","console","log","id","cols","page_url","parent","page_id","spbcTblRowActionsCallback","fileName","confirmation","firstChild","innerHTML","warning_default","confirmed","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","append","tabHeaderTemplate","tabBodyTemplate","after","spbcTblPaginationCallback","page","removeAttr","spbcTblSortCallback","domain","target","classList","contains","order_by","order","spbcScannerSwitchTable","_obj","spbcShowHideRows","blockId","columnKey","block","hasClass","removeClass","addClass","ready"],"mappings":"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"} \ No newline at end of file diff --git a/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/HeuristicAnalyser.php b/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/HeuristicAnalyser.php index 9e55118fd..ba6c716c8 100644 --- a/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/HeuristicAnalyser.php +++ b/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/HeuristicAnalyser.php @@ -17,6 +17,7 @@ use CleantalkSP\Common\Scanner\HeuristicAnalyser\Modules\Tokens; use CleantalkSP\Common\Scanner\HeuristicAnalyser\Modules\Transformations; use CleantalkSP\Common\Scanner\HeuristicAnalyser\Modules\Variables; +use CleantalkSP\Common\Scanner\HeuristicAnalyser\Modules\PHPCodeValidator; /** * Class Heuristic @@ -178,6 +179,11 @@ class HeuristicAnalyser */ private $mathematics; + /* + * @var PHPCodeValidator + */ + private $php_code_validator; + /** * Heuristic constructor. * Getting common info about file|text and it's content @@ -229,6 +235,8 @@ public function __construct($input, $self = null) $this->includes = new Includes($this->tokens, $this->variables, $this->curr_dir, $this->is_text); $this->evaluations = new Evaluations($this->tokens, $this->variables, $this->includes, $this->sqls); $this->code_style = new CodeStyle($this->tokens); + $this->php_code_validator = new PHPCodeValidator($this->tokens); + if ( isset($input['path']) && version_compare(PHP_VERSION, '8.1', '>=') && extension_loaded('mbstring') ) { // Do not run entropy analysis on included constructs @@ -276,12 +284,17 @@ private function checkFileSize($file_size) * * @return void * @psalm-suppress PossiblyUnusedMethod + * @throws HeuristicScannerException */ public function processContent() { // Skip files does not contain PHP code - if ( $this->extension !== 'php' && ! $this->code_style->hasPHPOpenTags() ) { - return; + if ( $this->extension !== 'php' && !$this->php_code_validator->hasCorrectPHPOpenTags() ) { + throw new HeuristicScannerException('NOT_PHP_CODE'); + } + + if (!$this->php_code_validator->isValidPHPCode()) { + throw new HeuristicScannerException('NOT_VALID_PHP_CODE'); } // Analysing code style diff --git a/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/CodeStyle.php b/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/CodeStyle.php index c5688c4ba..b7daf7df2 100644 --- a/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/CodeStyle.php +++ b/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/CodeStyle.php @@ -224,32 +224,6 @@ public function detectBadLines() return $result; } - /** - * Check if file contains PHP open tags ("<\?php" or `<\?`). - * @return bool - */ - public function hasPHPOpenTags() - { - foreach ( $this->tokens as $_token => $content ) { - if ( isset($content[0]) && isset($this->tokens->next1[0]) ) { - if ( $content[0] === 'T_OPEN_TAG' ) { - //check if open tag is short - $is_short = isset($content[1]) && $content[1] === 'tokens->next1[0] === 'T_WHITESPACE' || - // should be whitespaces or variable after tag - !$is_short && in_array($this->tokens->next1[0], array('T_WHITESPACE', 'T_VARIABLE')) - ) { - return true; - } - } - } - } - - return false; - } - /** * Count special service chars like <>!= etc. and return the proportion to the total chars count. * Uses $this->tokens as content source. diff --git a/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/PHPCodeValidator.php b/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/PHPCodeValidator.php new file mode 100644 index 000000000..335b85892 --- /dev/null +++ b/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/PHPCodeValidator.php @@ -0,0 +1,165 @@ +tokens = $tokens; + } + + /** + * Checks if the PHP code is valid. + * + * @return bool Returns true if the PHP code is valid, false otherwise. + * @psalm-suppress PossiblyUnusedMethod + */ + public function isValidPHPCode() + { + return ( + $this->hasCorrectPHPOpenTags() && + $this->checkBraces() && + $this->checkQuotes() && + $this->checkDigitsStartedVariables() + ); + } + + /** + * Checks if the count of left and right braces and brackets are equal. + * + * @return bool Returns true if the count is equal, false otherwise. + */ + private function checkBraces() + { + $braces_l_count = 0; + $braces_r_count = 0; + $brackets_l_count = 0; + $brackets_r_count = 0; + $parentheses_l_count = 0; + $parentheses_r_count = 0; + + foreach ( $this->tokens as $token ) { + if ( $token[0] === '__SERV' ) { + if ( $token[1] === '(' ) { + $braces_l_count++; + } + if ( $token[1] === ')' ) { + $braces_r_count++; + } + if ( $token[1] === '[' ) { + $brackets_l_count++; + } + if ( $token[1] === ']' ) { + $brackets_r_count++; + } + if ( $token[1] === '{' ) { + $parentheses_l_count++; + } + if ( $token[1] === '}' ) { + $parentheses_r_count++; + } + } + } + + if ( $braces_l_count !== $braces_r_count + || $brackets_l_count !== $brackets_r_count + || $parentheses_l_count !== $parentheses_r_count) { + $this->check_list_result['checkBraces'] = 'Braces or brackets count is not equal'; + return false; + } + return true; + } + + /** + * Checks if the count of single and double quotes are even. + * + * @return bool Returns true if the count is even, false otherwise. + */ + private function checkQuotes() + { + $double_quotes_count = 0; + $single_quotes_count = 0; + + foreach ( $this->tokens as $token ) { + if ( $token[0] === '__SERV' ) { + if ( $token[1] === '"' ) { + $double_quotes_count++; + } + if ( $token[1] === "'" ) { + $single_quotes_count++; + } + } + } + + if ( $double_quotes_count % 2 !== 0 || $single_quotes_count % 2 !== 0 ) { + $this->check_list_result['checkQuotes'] = 'Quotes count is not even'; + return false; + } + return true; + } + + /** + * Checks if variables contain digits. + * + * @return bool Returns true if no variables contain digits, false otherwise. + */ + private function checkDigitsStartedVariables() + { + foreach ( $this->tokens as $token ) { + if ( $token[0] === 'T_VARIABLE' ) { + if ( preg_match('/^\$\d.+/', $token[1]) ) { + $this->check_list_result['checkDigitsInVariables'] = 'Variable starts with digits [' . $token[1] . ']'; + return false; + } + } + } + return true; + } + + /** + * Checks if the file does not contain PHP open tags ("<\?php" or `<\?`). + * + * @return bool Returns true if the file does not contain PHP open tags, false otherwise. + */ + public function hasCorrectPHPOpenTags() + { + foreach ( $this->tokens as $_token => $content ) { + if ( isset($content[0]) && isset($this->tokens->next1[0]) ) { + if ( $content[0] === 'T_OPEN_TAG' ) { + //check if open tag is short + $is_short = isset($content[1]) && $content[1] === 'tokens->next1[0] !== 'T_WHITESPACE' ) { + $this->check_list_result['hasCorrectPHPOpenTags'] = 'PHP open tags are not valid'; + return false; + } + } else { + return true; + } + } + } + } + + return false; + } +} diff --git a/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/Tokens.php b/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/Tokens.php index 166b9829f..21e798634 100644 --- a/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/Tokens.php +++ b/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/Tokens.php @@ -66,6 +66,51 @@ class Tokens implements \Iterator, \ArrayAccess, \Countable */ private $groups; + /** + * @var Token|null $prev4 The fourth previous token in the iteration. + */ + public $prev4; + + /** + * @var Token|null $prev3 The third previous token in the iteration. + */ + public $prev3; + + /** + * @var Token|null $prev2 The second previous token in the iteration. + */ + public $prev2; + + /** + * @var Token|null $prev1 The first previous token in the iteration. + */ + public $prev1; + + /** + * @var Token|null $current The current token in the iteration. + */ + public $current; + + /** + * @var Token|null $next1 The first next token in the iteration. + */ + public $next1; + + /** + * @var Token|null $next2 The second next token in the iteration. + */ + public $next2; + + /** + * @var Token|null $next3 The third next token in the iteration. + */ + public $next3; + + /** + * @var Token|null $next4 The fourth next token in the iteration. + */ + public $next4; + /** * @param $content * @psalm-suppress PossiblyUnusedMethod @@ -646,6 +691,7 @@ public function count() * * @return Token|null * @psalm-suppress PossiblyUnusedReturnValue + * @psalm-suppress PossiblyUnusedMethod */ public function __get($name) { @@ -679,6 +725,7 @@ public function __get($name) /** * @param $name * @param $value + * @psalm-suppress PossiblyUnusedMethod */ public function __set($name, $value) { From 280def5b0852318887d4954ccb5cae43e89cd646 Mon Sep 17 00:00:00 2001 From: alexandergull Date: Wed, 5 Jun 2024 16:23:25 +0500 Subject: [PATCH 2/7] Mod. Scanner log. Files statuses layout. "ERROR" status has been modified to "SKIPPED". --- lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php | 12 ++++++++++++ .../SpbctWP/Scanner/ScanningLog/Repository.php | 2 ++ 2 files changed, 14 insertions(+) diff --git a/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php b/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php index 1a7331b3c..bb21ba995 100755 --- a/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php +++ b/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php @@ -1370,6 +1370,12 @@ public function signature_analysis($status = 'UNKNOWN,MODIFIED,OK,INFECTED,ERROR $stage_data_obj->increase('scanned_count_files', $scanned); $stage_data_obj->merge('statuses', $statuses->getStatuses()); + //modify error status to skipped - this will be shown in the log only + foreach ( $processed_items as $fast_hash => $item ) { + if ( $item['status'] === 'ERROR' ) { + $processed_items[$fast_hash]['status'] = 'SKIPPED'; + } + } // Adding data for user log $out['processed_items'] = $processed_items; @@ -1566,6 +1572,12 @@ public function heuristic_analysis($status = 'UNKNOWN,MODIFIED,OK,INFECTED,ERROR 'end' => (int)$scanned < $amount && !$size_breaking_flag, ); + //modify error status to skipped - this will be shown in the log only + foreach ( $processed_items as $fast_hash => $item ) { + if ( $item['status'] === 'ERROR' ) { + $processed_items[$fast_hash]['status'] = 'SKIPPED'; + } + } // Adding data for user log if ( $processed_items ) { $out['processed_items'] = $processed_items; diff --git a/lib/CleantalkSP/SpbctWP/Scanner/ScanningLog/Repository.php b/lib/CleantalkSP/SpbctWP/Scanner/ScanningLog/Repository.php index 48108a1e4..8a7fca9e0 100644 --- a/lib/CleantalkSP/SpbctWP/Scanner/ScanningLog/Repository.php +++ b/lib/CleantalkSP/SpbctWP/Scanner/ScanningLog/Repository.php @@ -8,6 +8,8 @@ class Repository { public static function write($content) { + //modify error status to skipped - this will be shown in the log only + $content = str_replace('ERROR', 'SKIPPED', $content); return DB::getInstance()->prepare( 'INSERT INTO ' . SPBC_TBL_SCAN_RESULTS_LOG From 8abb8ed844cec0a9681f951b686b7dbd279c9087 Mon Sep 17 00:00:00 2001 From: alexandergull Date: Wed, 5 Jun 2024 16:24:04 +0500 Subject: [PATCH 3/7] Fix. ScannerQueue. Error handling fixed. --- lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php b/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php index bb21ba995..9a4a17899 100755 --- a/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php +++ b/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php @@ -2420,7 +2420,7 @@ private static function handleErrorMsg($file_record_error, $new_error_msg, $type if (!in_array($type, ['signature_analysis', 'heuristic_analysis'])) { return ''; } - if (is_null($file_record_error)) { + if (is_null($new_error_msg)) { return ''; } $current_error_msg = json_decode($file_record_error, true); From bb0fc8e137a0e6964720489aeaf20cf4cb43a66d Mon Sep 17 00:00:00 2001 From: alexandergull Date: Wed, 5 Jun 2024 17:23:00 +0500 Subject: [PATCH 4/7] Fix. ScannerQueue. Heuristic. Do not set "ERROR" status for files taht suceesfully checked with Signatures. --- .../SpbctWP/Scanner/ScannerQueue.php | 51 +++++++++++-------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php b/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php index 9a4a17899..b618d16c1 100755 --- a/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php +++ b/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php @@ -1534,26 +1534,37 @@ public function heuristic_analysis($status = 'UNKNOWN,MODIFIED,OK,INFECTED,ERROR $scanned = 5; } } - - $current_error_msg = self::handleErrorMsg($file['error_msg'], $result->error_msg, 'heuristic_analysis'); - - $error_msg = !empty($current_error_msg) - ? '\'' . $current_error_msg . '\'' - : 'NULL'; - - $result_db = $this->db->execute( - 'UPDATE ' . SPBC_TBL_SCAN_FILES - . ' SET ' - . ' checked_heuristic = 1,' - . ' status = \'' . ($file['status'] === 'MODIFIED' ? 'MODIFIED' : $result->status) . '\',' - . ' severity = ' . ($file['severity'] ? '\'' . $file['severity'] . '\'' : ($result->severity ? '\'' . $result->severity . '\'' : 'NULL')) . ',' - . ' weak_spots = ' . ($result->weak_spots - ? QueueHelper::prepareParamForSQLQuery(json_encode($result->weak_spots)) - : 'NULL') - . ',' - . ' error_msg = ' . $error_msg - . ' WHERE fast_hash = \'' . $file['fast_hash'] . '\';' - ); + /** + * If heuristic analysis failed, but file was successfully checked by signatures, just update as checked_heuristic + */ + if ($result->status === 'ERROR' && $file['status'] !== 'ERROR' && !empty($file['severity'])) { + $result_db = $this->db->execute( + 'UPDATE ' . SPBC_TBL_SCAN_FILES + . ' SET ' + . ' checked_heuristic = 1' + . ' WHERE fast_hash = \'' . $file['fast_hash'] . '\';' + ); + } else { + $current_error_msg = self::handleErrorMsg($file['error_msg'], $result->error_msg, 'heuristic_analysis'); + + $error_msg = !empty($current_error_msg) + ? '\'' . $current_error_msg . '\'' + : 'NULL'; + + $result_db = $this->db->execute( + 'UPDATE ' . SPBC_TBL_SCAN_FILES + . ' SET ' + . ' checked_heuristic = 1,' + . ' status = \'' . ($file['status'] === 'MODIFIED' ? 'MODIFIED' : $result->status) . '\',' + . ' severity = ' . ($file['severity'] ? '\'' . $file['severity'] . '\'' : ($result->severity ? '\'' . $result->severity . '\'' : 'NULL')) . ',' + . ' weak_spots = ' . ($result->weak_spots + ? QueueHelper::prepareParamForSQLQuery(json_encode($result->weak_spots)) + : 'NULL') + . ',' + . ' error_msg = ' . $error_msg + . ' WHERE fast_hash = \'' . $file['fast_hash'] . '\';' + ); + } $statuses->addStatus($file['status'] === 'MODIFIED' ? 'MODIFIED' : $result->status); From 58dcec7e531a4816c78adc75741c5cc94895c70e Mon Sep 17 00:00:00 2001 From: alexandergull Date: Wed, 5 Jun 2024 17:23:33 +0500 Subject: [PATCH 5/7] Fix. ScannerQueue. Cure. Do not update file if heuristic recheck fails. --- lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php b/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php index b618d16c1..90b6f8a9b 100755 --- a/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php +++ b/lib/CleantalkSP/SpbctWP/Scanner/ScannerQueue.php @@ -1819,7 +1819,7 @@ public function auto_cure($offset = 0, $amount = 1) // phpcs:ignore PSR1.Methods $file_to_check = new FileInfoExtended($file); $result = $heuristic_scanner->scanFile($file_to_check, $root_path); - if ( is_object($result) ) { + if ( is_object($result) && $result->status !== 'ERROR') { $this->db->execute( 'UPDATE ' . SPBC_TBL_SCAN_FILES . ' SET' From dc8bc3f0b57961b3f1c3d6a3a319cc5c66d8e8f1 Mon Sep 17 00:00:00 2001 From: alexandergull Date: Wed, 19 Jun 2024 15:40:24 +0500 Subject: [PATCH 6/7] Mod. PHPCodeValidator. Split checks. --- .../Modules/PHPCodeValidator.php | 98 +++++++++++++++---- 1 file changed, 81 insertions(+), 17 deletions(-) diff --git a/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/PHPCodeValidator.php b/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/PHPCodeValidator.php index 335b85892..4e59005be 100644 --- a/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/PHPCodeValidator.php +++ b/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/PHPCodeValidator.php @@ -39,7 +39,10 @@ public function isValidPHPCode() return ( $this->hasCorrectPHPOpenTags() && $this->checkBraces() && - $this->checkQuotes() && + $this->checkBrackets() && + $this->checkParentheses() && + $this->checkSingleQuotes() && + $this->checkDoubleQuotes() && $this->checkDigitsStartedVariables() ); } @@ -53,10 +56,6 @@ private function checkBraces() { $braces_l_count = 0; $braces_r_count = 0; - $brackets_l_count = 0; - $brackets_r_count = 0; - $parentheses_l_count = 0; - $parentheses_r_count = 0; foreach ( $this->tokens as $token ) { if ( $token[0] === '__SERV' ) { @@ -66,12 +65,58 @@ private function checkBraces() if ( $token[1] === ')' ) { $braces_r_count++; } + } + } + + if ( $braces_l_count !== $braces_r_count ) { + $this->check_list_result[__METHOD__] = 'Braces () count is not equal'; + return false; + } + + return true; + } + + /** + * Checks if the count of left and right brackets are equal. + * + * @return bool Returns true if the count is equal, false otherwise. + */ + private function checkBrackets() + { + $brackets_l_count = 0; + $brackets_r_count = 0; + + foreach ( $this->tokens as $token ) { + if ( $token[0] === '__SERV' ) { if ( $token[1] === '[' ) { $brackets_l_count++; } if ( $token[1] === ']' ) { $brackets_r_count++; } + } + } + + if ( $brackets_l_count !== $brackets_r_count ) { + $this->check_list_result[__METHOD__] = 'Brackets [] count is not equal'; + return false; + } + + return true; + } + + /** + * Checks if the count of left and right parentheses are equal. + * + * @return bool Returns true if the count is equal, false otherwise. + */ + private function checkParentheses() + { + $parentheses_l_count = 0; + $parentheses_r_count = 0; + + foreach ( $this->tokens as $token ) { + if ( $token[0] === '__SERV' ) { if ( $token[1] === '{' ) { $parentheses_l_count++; } @@ -81,38 +126,57 @@ private function checkBraces() } } - if ( $braces_l_count !== $braces_r_count - || $brackets_l_count !== $brackets_r_count - || $parentheses_l_count !== $parentheses_r_count) { - $this->check_list_result['checkBraces'] = 'Braces or brackets count is not equal'; + if ( $parentheses_l_count !== $parentheses_r_count ) { + $this->check_list_result[__METHOD__] = 'Parentheses {} count is not equal'; return false; } + return true; } /** - * Checks if the count of single and double quotes are even. + * Checks if the count of single quotes are even. * * @return bool Returns true if the count is even, false otherwise. */ - private function checkQuotes() + private function checkSingleQuotes() { - $double_quotes_count = 0; $single_quotes_count = 0; foreach ( $this->tokens as $token ) { if ( $token[0] === '__SERV' ) { - if ( $token[1] === '"' ) { - $double_quotes_count++; - } if ( $token[1] === "'" ) { $single_quotes_count++; } } } - if ( $double_quotes_count % 2 !== 0 || $single_quotes_count % 2 !== 0 ) { - $this->check_list_result['checkQuotes'] = 'Quotes count is not even'; + if ( $single_quotes_count % 2 !== 0 ) { + $this->check_list_result['checkQuotes'] = 'Single quotes count is not even'; + return false; + } + return true; + } + + /** + * Checks if the count of double quotes are even. + * + * @return bool Returns true if the count is even, false otherwise. + */ + private function checkDoubleQuotes() + { + $double_quotes_count = 0; + + foreach ( $this->tokens as $token ) { + if ( $token[0] === '__SERV' ) { + if ( $token[1] === '"' ) { + $double_quotes_count++; + } + } + } + + if ( $double_quotes_count % 2 !== 0 ) { + $this->check_list_result['checkQuotes'] = 'Double quotes count is not even'; return false; } return true; From 9ed4b7f69675d04d0220b266c98e042f4cf8070a Mon Sep 17 00:00:00 2001 From: alexandergull Date: Wed, 19 Jun 2024 19:31:02 +0500 Subject: [PATCH 7/7] Mod. PHPCodeValidator. Open parenthesis logic updated. --- .../Modules/PHPCodeValidator.php | 60 ++++++++++++------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/PHPCodeValidator.php b/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/PHPCodeValidator.php index 4e59005be..0ff4241d9 100644 --- a/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/PHPCodeValidator.php +++ b/lib/CleantalkSP/Common/Scanner/HeuristicAnalyser/Modules/PHPCodeValidator.php @@ -36,15 +36,14 @@ public function __construct($tokens) */ public function isValidPHPCode() { - return ( - $this->hasCorrectPHPOpenTags() && - $this->checkBraces() && - $this->checkBrackets() && - $this->checkParentheses() && - $this->checkSingleQuotes() && - $this->checkDoubleQuotes() && - $this->checkDigitsStartedVariables() - ); + $this->hasCorrectPHPOpenTags(); + $this->checkBraces(); + $this->checkBrackets(); + $this->checkParentheses(); + $this->checkSingleQuotes(); + $this->checkDoubleQuotes(); + $this->checkDigitsStartedVariables(); + return empty($this->check_list_result); } /** @@ -69,7 +68,7 @@ private function checkBraces() } if ( $braces_l_count !== $braces_r_count ) { - $this->check_list_result[__METHOD__] = 'Braces () count is not equal'; + $this->check_list_result[__FUNCTION__] = 'Braces () count is not equal ' . $braces_l_count . ' != ' . $braces_r_count; return false; } @@ -98,7 +97,7 @@ private function checkBrackets() } if ( $brackets_l_count !== $brackets_r_count ) { - $this->check_list_result[__METHOD__] = 'Brackets [] count is not equal'; + $this->check_list_result[__FUNCTION__] = 'Brackets [] count is not equal'; return false; } @@ -115,19 +114,34 @@ private function checkParentheses() $parentheses_l_count = 0; $parentheses_r_count = 0; + /** + * init opening and closing tokens, key is token type, value is string to search + */ + $opening_tokens = array( + '__SERV' => '{', + 'T_CURLY_OPEN' => '{', + 'T_DOLLAR_OPEN_CURLY_BRACES' => '${', + 'T_STRING_VARNAME' => '{' + ); + + $closing_tokens = array( + '__SERV' => '}', + 'T_STRING_VARNAME' => '}' + ); + foreach ( $this->tokens as $token ) { - if ( $token[0] === '__SERV' ) { - if ( $token[1] === '{' ) { - $parentheses_l_count++; - } - if ( $token[1] === '}' ) { - $parentheses_r_count++; - } + if ( isset($opening_tokens[$token[0]]) && + $token[1] === $opening_tokens[$token[0]] ) { + $parentheses_l_count++; + } + if ( isset($closing_tokens[$token[0]]) && + $token[1] === $closing_tokens[$token[0]] ) { + $parentheses_r_count++; } } if ( $parentheses_l_count !== $parentheses_r_count ) { - $this->check_list_result[__METHOD__] = 'Parentheses {} count is not equal'; + $this->check_list_result[__FUNCTION__] = 'Parentheses {} count is not equal'; return false; } @@ -152,7 +166,7 @@ private function checkSingleQuotes() } if ( $single_quotes_count % 2 !== 0 ) { - $this->check_list_result['checkQuotes'] = 'Single quotes count is not even'; + $this->check_list_result[__FUNCTION__] = 'Single quotes count is not even'; return false; } return true; @@ -176,7 +190,7 @@ private function checkDoubleQuotes() } if ( $double_quotes_count % 2 !== 0 ) { - $this->check_list_result['checkQuotes'] = 'Double quotes count is not even'; + $this->check_list_result[__FUNCTION__] = 'Double quotes count is not even'; return false; } return true; @@ -192,7 +206,7 @@ private function checkDigitsStartedVariables() foreach ( $this->tokens as $token ) { if ( $token[0] === 'T_VARIABLE' ) { if ( preg_match('/^\$\d.+/', $token[1]) ) { - $this->check_list_result['checkDigitsInVariables'] = 'Variable starts with digits [' . $token[1] . ']'; + $this->check_list_result[__FUNCTION__] = 'Variable starts with digits [' . $token[1] . ']'; return false; } } @@ -214,7 +228,7 @@ public function hasCorrectPHPOpenTags() $is_short = isset($content[1]) && $content[1] === 'tokens->next1[0] !== 'T_WHITESPACE' ) { - $this->check_list_result['hasCorrectPHPOpenTags'] = 'PHP open tags are not valid'; + $this->check_list_result[__FUNCTION__] = 'PHP open tags are not valid'; return false; } } else {