diff --git a/administrator/components/com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini b/administrator/components/com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini index a228002..9492195 100644 --- a/administrator/components/com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini +++ b/administrator/components/com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini @@ -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 Project's homepage
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 :" diff --git a/administrator/components/com_jedchecker/libraries/rules/framework.ini b/administrator/components/com_jedchecker/libraries/rules/framework.ini index fc3db99..ec1c54d 100644 --- a/administrator/components/com_jedchecker/libraries/rules/framework.ini +++ b/administrator/components/com_jedchecker/libraries/rules/framework.ini @@ -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" diff --git a/administrator/components/com_jedchecker/libraries/rules/framework.php b/administrator/components/com_jedchecker/libraries/rules/framework.php index a60d12a..3bbb9dc 100644 --- a/administrator/components/com_jedchecker/libraries/rules/framework.php +++ b/administrator/components/com_jedchecker/libraries/rules/framework.php @@ -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, '' . $singleTest . '', htmlspecialchars($origLine)); + $origLine = str_ireplace($singleTest->test, '' . $singleTest->test . '', htmlspecialchars($origLine)); $error_message = Text::_('COM_JEDCHECKER_ERROR_FRAMEWORK_' . strtoupper($testObject->group)) . ':
' . $origLine . '
'; + 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'); + } }