fix and improve processing of deprecated framework api

This commit is contained in:
Denis Ryabov 2023-09-05 12:11:38 +04:00
parent eee90541ed
commit aac5e96bef
3 changed files with 73 additions and 24 deletions

View File

@ -85,6 +85,7 @@ COM_JEDCHECKER_ERROR_FRAMEWORK_LEFTOVER_FOLDER="Leftover folder detected"
COM_JEDCHECKER_ERROR_FRAMEWORK_LEFTOVER_FILE="Leftover file detected"
COM_JEDCHECKER_ERROR_FRAMEWORK_STRICT="PHP Strict Standards: Only variables should be assigned by reference"
COM_JEDCHECKER_ERROR_FRAMEWORK_LEADING_SPACES="Spaces at the beginning of PHP file detected (it might result in the 'Cannot modify header information - headers already sent' warning message)"
COM_JEDCHECKER_ERROR_FRAMEWORK_INSTEAD_USE="Instead use"
COM_JEDCHECKER_RULE_JAMSS="JAMSS - Joomla! Anti-Malware Scan Script"
COM_JEDCHECKER_RULE_JAMSS_DESC="JAMSS will raise many flags for use of potentially dangerous methods, additionally checking for some known attack signatures. Find out more on the <a href='https://github.com/btoplak/Joomla-Anti-Malware-Scan-Script' target='_blank'>Project's homepage</a><br>JAMSS output is very verbose and very useful, hover over any lines to see the details."
COM_JEDCHECKER_ERROR_JAMSS_SUSPICIOUS_FILENAME="Suspicious filename found :"

View File

@ -34,9 +34,9 @@ todo="@TODO"
compatibility_groups="notinj3,notinj4,deprecated,deprecatedinj4,jerr,DS,strict"
notinj3="JUtility::isWinOS,JFTP,JLDAP,JWebClient,JloadResultArray,nameQuote,JRequest::checkToken,JParameter,JElement,JFormFieldEditors,JHtmlImage,JRules,JSimpleXML,JPane,$db->getEscaped,JDate::toMysql,JUtility::sendMail,JUtility::sendAdminMail,JUtility::getToken,JFactory::getXMLParser,JDate::toMysql"
notinj4="JInstallerComponent,JInstallerFile,JInstallerLanguage,JInstallerLibrary,JInstallerModule,JInstallerPackage,JInstallerPlugin,JInstallerTemplate,JSubMenuHelper,pagination_item_active,pagination_item_inactive,JVersion::RELEASE,JVersion::DEV_LEVEL,JVersion::BUILD,JHtmlBootstrap::modal,JHtml::_('bootstrap.modal',JHtmlBatch,JHtml::_('batch.,JAccess::$assetPermissionsById,JAccess::$assetPermissionsByName,JAccess::preloadPermissionsParentIdMapping,JAccess::getActions,JApplicationWebRouter,JApplicationWebRouterBase,JApplicationWebRouterRest,$app->getPageParameters,JApplicationHelper::parseXMLLangMetaFile,JCrypt::hasStrongPasswordSupport,JCacheStorage::test,JFactory::getXml,Factory::getXml,JFactory::getEditor,Factory::getEditor,JFilterInput::_,JNode,JTree,JGrid,JArrayHelper,$_PROFILER"
notinj4="JInstallerComponent=>JInstallerAdapterComponent,JInstallerFile=>JInstallerAdapterFile,JInstallerLanguage=>JInstallerAdapterLanguage,JInstallerLibrary=>JInstallerAdapterLibrary,JInstallerModule=>JInstallerAdapterModule,JInstallerPackage=>JInstallerAdapterPackage,JInstallerPlugin=>JInstallerAdapterPlugin,JInstallerTemplate=>JInstallerAdapterTemplate,JSubMenuHelper=>JHtmlSidebar,pagination_item_active=>JLayout joomla.pagination.link,pagination_item_inactive=>JLayout joomla.pagination.link,JVersion::RELEASE,JVersion::DEV_LEVEL,JVersion::BUILD,JHtmlBootstrap::modal=>JHtmlBootstrap::renderModal,JHtml::_('bootstrap.modal'=>JHtml::_('bootstrap.renderModal',JHtmlBatch=>JLayouts,JHtml::_('batch.,JAccess::$assetPermissionsById,JAccess::$assetPermissionsByName,JAccess::preloadPermissionsParentIdMapping,JAccess::getActions=>JAccess::getActionsFromFile/JAccess::getActionsFromData,JApplicationWebRouter=>joomla/router package,JApplicationWebRouterBase=>joomla/router package,JApplicationWebRouterRest=>joomla/router package,->isSite()=>isClient,->isAdmin()=>isClient,$app->getPageParameters=>getParams,JApplicationHelper::parseXMLLangMetaFile,JCrypt::hasStrongPasswordSupport,JCryptCipher3Des=>JCryptCipherCryptoбJCryptCipherBlowfish=>JCryptCipherCrypto,JCryptCipherMcrypt=>JCryptCipherCrypto,JCryptCipherRijndael256=>JCryptCipherCrypto,JCryptCipherSimpleJCacheStorage::test,JFactory::getXml=>SimpleXMLElement,Factory::getXml=>SimpleXMLElement,JFactory::getEditor=>JEditor::getInstance,Factory::getEditor=>JEditor::getInstance,JFactory::getUri=>Uri::getInstance,Factory::getUri=>Uri::getInstance,JBrowser::isSSLConnection=>JApplicationCms::isSSLConnection,JFilterInput::_,JNode,JTree,JGrid,JArrayHelper=>Joomla\\Utilities\\ArrayHelper,$_PROFILER=>Joomla\\CMS\\Profiler\\Profiler::getInstance,JProfiler::getmicrotime,JProfiler::getMemory,JMail::sendAdminMail,JString=>Joomla\\String\\StringHelper"
deprecated="JHtmlBehavior::mootools,JHtml::_('behavior.mootools',JRequest,->assignRef"
deprecatedinj4="pagination_list_render,JHtmlSortablelist::sortable,JHtml::_('sortablelist.sortable',JApplicationBase"
deprecatedinj4="pagination_list_render=>JLayout joomla.pagination.list,JHtmlSortablelist::sortable=>JHtmlDraggablelist::draggable,JHtml::_('sortablelist.sortable'=>JHtml::_('draggablelist.draggable',JApplicationBase=>Joomla\\Application\\AbstractApplication"
jerr="JError::"
DS=" DS ,.DS., DS.,.DS "
strict="&JFactory,&JModuleHelper"

View File

@ -169,24 +169,31 @@ class JedcheckerRulesFramework extends JEDcheckerRule
}
// Clean non-code
$content = JEDCheckerHelper::cleanPhpCode(
$cleanContent = JEDCheckerHelper::cleanPhpCode(
$content,
JEDCheckerHelper::CLEAN_HTML | JEDCheckerHelper::CLEAN_COMMENTS | JEDCheckerHelper::CLEAN_STRINGS
);
$cleanContent = JEDCheckerHelper::splitLines($content);
// Check short PHP tag
if (preg_match('/<\?\s/', $content, $match, PREG_OFFSET_CAPTURE))
if (preg_match('/<\?\s/', $cleanContent, $match, PREG_OFFSET_CAPTURE))
{
$lineno = substr_count($content, "\n", 0, $match[0][1]);
$lineno = substr_count($cleanContent, "\n", 0, $match[0][1]);
$this->report->addError($file, Text::_('COM_JEDCHECKER_ERROR_FRAMEWORK_SHORT_PHP_TAG'), $lineno + 1, $origContent[$lineno]);
$result = true;
}
$cleanContentKeepStrings = JEDCheckerHelper::cleanPhpCode(
$content,
JEDCheckerHelper::CLEAN_HTML | JEDCheckerHelper::CLEAN_COMMENTS
);
$cleanContent = JEDCheckerHelper::splitLines($cleanContent);
$cleanContentKeepStrings = JEDCheckerHelper::splitLines($cleanContentKeepStrings);
// Run other tests
foreach ($this->getTests() as $testObject)
{
if ($this->runTest($file, $origContent, $cleanContent, $testObject))
if ($this->runTest($file, $origContent, $cleanContent, $cleanContentKeepStrings, $testObject))
{
$result = true;
}
@ -201,11 +208,12 @@ class JedcheckerRulesFramework extends JEDcheckerRule
* @param string $file The file name
* @param array $origContent The file content
* @param array $cleanContent The file content w/o non-code elements
* @param array $cleanContentKeepStrings The file content w/o comments and HTML
* @param object $testObject The test object generated by getTests()
*
* @return boolean
*/
private function runTest($file, $origContent, $cleanContent, $testObject)
private function runTest($file, $origContent, $cleanContent, $cleanContentKeepStrings, $testObject)
{
// @todo remove as unused?
$error_count = 0;
@ -216,25 +224,18 @@ class JedcheckerRulesFramework extends JEDcheckerRule
foreach ($testObject->tests as $singleTest)
{
$regex = preg_quote($singleTest, '/');
$lineContent = $singleTest->keepStrings ? $cleanContentKeepStrings[$line_number] : $line;
// Add word boundary check for rules staring/ending with a letter (to avoid false-positives because of partial match)
if (ctype_alpha($singleTest[0]))
if (preg_match($singleTest->regex, $lineContent))
{
$regex = '\b' . $regex;
}
if (ctype_alpha($singleTest[strlen($singleTest) - 1]))
{
$regex .= '\b';
}
if (preg_match('/' . $regex . '/i', $line))
{
$origLine = str_ireplace($singleTest, '<b>' . $singleTest . '</b>', htmlspecialchars($origLine));
$origLine = str_ireplace($singleTest->test, '<b>' . $singleTest->test . '</b>', htmlspecialchars($origLine));
$error_message = Text::_('COM_JEDCHECKER_ERROR_FRAMEWORK_' . strtoupper($testObject->group)) . ':<pre>' . $origLine . '</pre>';
if ($singleTest->replacement !== false)
{
$error_message .= Text::_('COM_JEDCHECKER_ERROR_FRAMEWORK_INSTEAD_USE') . ': ' . $singleTest->replacement;
}
switch ($testObject->kind)
{
case 'error':
@ -290,7 +291,28 @@ class JedcheckerRulesFramework extends JEDcheckerRule
$newTest = new stdClass;
$newTest->group = $group;
$newTest->kind = $test;
$newTest->tests = explode(",", $this->params->get($group));
$newTest->tests = array();
foreach (explode(",", $this->params->get($group)) as $test)
{
if (strpos($test, '=>') !== false)
{
list($test, $replacement) = explode('=>', $test, 2);
}
else
{
$replacement = false;
}
$testObj = new stdClass;
$testObj->test = $test;
$testObj->regex = $this->generateRegex($test);
$testObj->replacement = $replacement;
$testObj->keepStrings = strpos($test, "'") !== false;
$newTest->tests[] = $testObj;
}
$this->tests[] = $newTest;
}
}
@ -298,4 +320,30 @@ class JedcheckerRulesFramework extends JEDcheckerRule
return $this->tests;
}
/**
* Generates regular expression for a given test
*
* @param string $test The string to match
* @param boolean $matchCase True for case-sensitive matching
*
* @return string
*/
private function generateRegex($test, $matchCase = false)
{
$regex = preg_quote($test, '/');
// Add word boundary check for rules staring/ending with a letter (to avoid false-positives because of partial match)
if (ctype_alpha($test[0]))
{
$regex = '\b' . $regex;
}
if (ctype_alpha($test[strlen($test) - 1]))
{
$regex .= '\b';
}
return '/' . $regex . '/' . ($matchCase ? '' : 'i');
}
}