33
2
mirror of https://github.com/joomla-extensions/jedchecker.git synced 2024-11-30 16:53:59 +00:00

Merge PR #107 into develop

This commit is contained in:
Llewellyn van der Merwe 2021-08-31 11:57:37 +02:00
commit dde14f6869
Signed by: Llewellyn
GPG Key ID: EFC0C720A240551C
3 changed files with 129 additions and 39 deletions

View File

@ -66,17 +66,22 @@ COM_JEDCHECKER_OLD_RULE_X_PHP_FILE_NOT_REMOVED="PHP file for '%s' rule could not
COM_JEDCHECKER_OLD_RULE_X_PHP_FILE_REMOVED="Removed PHP file for '%s' rule." COM_JEDCHECKER_OLD_RULE_X_PHP_FILE_REMOVED="Removed PHP file for '%s' rule."
COM_JEDCHECKER_OLD_RULE_X_INI_FILE_REMOVED="Removed 'ini' file for '%s' rule." COM_JEDCHECKER_OLD_RULE_X_INI_FILE_REMOVED="Removed 'ini' file for '%s' rule."
COM_JEDCHECKER_RULE_FRAMEWORK="Joomla Framework deprecated and unsafe" COM_JEDCHECKER_RULE_FRAMEWORK="Joomla Framework deprecated and unsafe"
COM_JEDCHECKER_RULE_FRAMEWORK_DESC="Warns about <ul><li>superglobals</li><li>commonly used but deprecated functions</li><li>highly unsafe functions</li></ul>Find more info <a href='http://docs.joomla.org/Potential_backward_compatibility_issues_in_Joomla_3.0_and_Joomla_Platform_12.1' target='_blank'>on Joomla backward compatibility for Joomla 3</a>" COM_JEDCHECKER_RULE_FRAMEWORK_DESC="Warns about <ul><li>superglobals</li><li>commonly used but deprecated functions</li><li>highly unsafe functions</li></ul>Find more info <a href='https://docs.joomla.org/Potential_backward_compatibility_issues_in_Joomla_3.0_and_Joomla_Platform_12.1' target='_blank'>on Joomla! backward compatibility for Joomla! 3</a> and <a href="https://docs.joomla.org/Potential_backward_compatibility_issues_in_Joomla_4">Joomla! 4</a>"
COM_JEDCHECKER_ERROR_FRAMEWORK_BOM_FOUND="The byte order mark (BOM) is detected. Please, save the file in the 'UTF-8 without BOM' format."
COM_JEDCHECKER_ERROR_FRAMEWORK_SHORT_PHP_TAG="Short PHP tag found. As short tags can be disabled in PHP, it is recommended to only use the normal tags (&lt;?php) to maximise compatibility."
COM_JEDCHECKER_ERROR_FRAMEWORK_SUPERGLOBALS="Use of superglobals is strongly discouraged" COM_JEDCHECKER_ERROR_FRAMEWORK_SUPERGLOBALS="Use of superglobals is strongly discouraged"
COM_JEDCHECKER_ERROR_FRAMEWORK_DIRECTDB="Use of direct database access is strongly discouraged" COM_JEDCHECKER_ERROR_FRAMEWORK_DIRECTDB="Use of direct database access is strongly discouraged"
COM_JEDCHECKER_RULE_FRAMEWORK_NOTINJ3="Functions deprecated in Joomla 3" COM_JEDCHECKER_RULE_FRAMEWORK_NOTINJ3="Functions deprecated in Joomla 3"
COM_JEDCHECKER_ERROR_FRAMEWORK_NOTINJ3="deprecated in Joomla 3" COM_JEDCHECKER_ERROR_FRAMEWORK_NOTINJ3="deprecated in Joomla 3"
COM_JEDCHECKER_ERROR_FRAMEWORK_NOTINJ4="removed in Joomla! 4"
COM_JEDCHECKER_ERROR_FRAMEWORK_DS="DS is deprecated in Joomla 3" COM_JEDCHECKER_ERROR_FRAMEWORK_DS="DS is deprecated in Joomla 3"
COM_JEDCHECKER_ERROR_FRAMEWORK_JERR="JError is deprecated, you should use JFactory::getApplication()->enqueueMessage();" COM_JEDCHECKER_ERROR_FRAMEWORK_JERR="JError is deprecated, you should use JFactory::getApplication()->enqueueMessage();"
COM_JEDCHECKER_ERROR_FRAMEWORK_ERRORLOG="error_log and var_dump" COM_JEDCHECKER_ERROR_FRAMEWORK_ERRORLOG="error_log and var_dump"
COM_JEDCHECKER_ERROR_FRAMEWORK_DEPRECATED="JRequest is deprecated, you should use JFactory::getApplication()->input;" COM_JEDCHECKER_ERROR_FRAMEWORK_DEPRECATED="JRequest is deprecated, you should use JFactory::getApplication()->input;"
COM_JEDCHECKER_ERROR_FRAMEWORK_DEPRECATEDINJ4="deprecated in Joomla! 4"
COM_JEDCHECKER_ERROR_FRAMEWORK_TODO="TODO statement detected" COM_JEDCHECKER_ERROR_FRAMEWORK_TODO="TODO statement detected"
COM_JEDCHECKER_ERROR_FRAMEWORK_GIT="Code-versioning folders detected" 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_STRICT="PHP Strict Standards: Only variables should be assigned by reference"
COM_JEDCHECKER_RULE_JAMSS="JAMSS - Joomla! Anti-Malware Scan Script" 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_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."

View File

@ -19,7 +19,8 @@
; ;
; ref: docs.joomla.org/Potential_backward_compatibility_issues_in_Joomla_3.0_and_Joomla_Platform_12.1 ; ref: docs.joomla.org/Potential_backward_compatibility_issues_in_Joomla_3.0_and_Joomla_Platform_12.1
leftover_folders=".DS_Store,.svn,.git" leftover_folders="__MACOSX,Desktop.ini,desktop.ini,Thumbs.db,node_modules,php-cs-fixer,phpcs,PHP_CodeSniffer,php_codesniffer,.*,*.bak,*.orig,*.php.*,*.test,*.tmp,*~,*.log,*_log,*.lock,*.pid,*.diff,*.patch,*.phar"
leftover_folders_whitelist=".htaccess"
error_groups="directdb" error_groups="directdb"
directdb="mysql_connect,mysql_query,mysql_close,mysql_escape_string,new mysqli,mysqli_connect,mysqli_query,mysqli_close,mysqli_escape_string,mysqli_real_escape_string" directdb="mysql_connect,mysql_query,mysql_close,mysql_escape_string,new mysqli,mysqli_connect,mysqli_query,mysqli_close,mysqli_escape_string,mysqli_real_escape_string"
@ -28,12 +29,14 @@ warning_groups="superglobals"
superglobals="$_GET,$_POST,$_SESSION,$_COOKIE,$_FILES" superglobals="$_GET,$_POST,$_SESSION,$_COOKIE,$_FILES"
notice_groups="errorlog,todo" notice_groups="errorlog,todo"
errorlog="error_log,var_export,var_dump,print_r" errorlog="error_log,var_export,var_dump,print_r,debug_zval_dump"
todo="@TODO" todo="@TODO"
compatibility_groups="notinj3,deprecated,jerr,DS,strict" 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" 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"
deprecated="JHtmlBehavior::mootools,JRequest,::assignRef" 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"
deprecated="JHtmlBehavior::mootools,JHtml::_('behavior.mootools',JRequest,->assignRef"
deprecatedinj4="pagination_list_render,JHtmlSortablelist::sortable,JHtml::_('sortablelist.sortable',JApplicationBase"
jerr="JError::" jerr="JError::"
DS=" DS ,.DS., DS.,.DS " DS=" DS ,.DS., DS.,.DS "
strict="&JFactory,&JModuleHelper" strict="&JFactory,&JModuleHelper"

View File

@ -14,6 +14,9 @@ defined('_JEXEC') or die('Restricted access');
// Include the rule base class // Include the rule base class
require_once JPATH_COMPONENT_ADMINISTRATOR . '/models/rule.php'; require_once JPATH_COMPONENT_ADMINISTRATOR . '/models/rule.php';
// Include the helper class
require_once JPATH_COMPONENT_ADMINISTRATOR . '/libraries/helper.php';
/** /**
* JedcheckerRulesFramework * JedcheckerRulesFramework
* *
@ -52,7 +55,7 @@ class JedcheckerRulesFramework extends JEDcheckerRule
protected $tests = false; protected $tests = false;
protected $leftover_folders; protected $regexLeftoverFolders;
/** /**
* Initiates the file search and check * Initiates the file search and check
@ -61,8 +64,47 @@ class JedcheckerRulesFramework extends JEDcheckerRule
*/ */
public function check() public function check()
{ {
// Warn about code versioning files included
$leftoverFolders = $this->params->get('leftover_folders');
$leftoverFoldersWhitelist = $this->params->get('leftover_folders_whitelist');
$this->regexLeftoverFolders = '';
if (!empty($leftoverFoldersWhitelist))
{
$this->regexLeftoverFolders .=
'(?!(?:'
. str_replace(array(',', '\*'), array('|', '.*'), preg_quote($leftoverFoldersWhitelist, '/'))
. '))';
}
$this->regexLeftoverFolders .= '(?:' . str_replace(array(',', '\*'), array('|', '.*'), preg_quote($leftoverFolders, '/')) . ')';
$regexLeftoverFolders = '^' . $this->regexLeftoverFolders . '$';
// Get matched files and folder (w/o default exclusion list)
$folders = JFolder::folders($this->basedir, $regexLeftoverFolders, true, true, array(), array());
$files = JFolder::files($this->basedir, $regexLeftoverFolders, true, true, array(), array());
if ($folders !== false)
{
// Warn on leftover folders found
foreach ($folders as $folder)
{
$this->report->addWarning($folder, JText::_("COM_JEDCHECKER_ERROR_FRAMEWORK_LEFTOVER_FOLDER"));
}
}
if ($files !== false)
{
// Warn on leftover files found
foreach ($files as $file)
{
$this->report->addWarning($file, JText::_("COM_JEDCHECKER_ERROR_FRAMEWORK_LEFTOVER_FILE"));
}
}
$files = JFolder::files($this->basedir, '\.php$', true, true); $files = JFolder::files($this->basedir, '\.php$', true, true);
$this->leftover_folders = explode(',', $this->params->get('leftover_folders'));
foreach ($files as $file) foreach ($files as $file)
{ {
@ -78,7 +120,7 @@ class JedcheckerRulesFramework extends JEDcheckerRule
} }
/** /**
* Check if the given resourse is part * Check if the given resource is inside of a leftover folder
* *
* @param string $file The file name to test * @param string $file The file name to test
* *
@ -86,20 +128,7 @@ class JedcheckerRulesFramework extends JEDcheckerRule
*/ */
private function excludeResource($file) private function excludeResource($file)
{ {
// Warn about code versioning files included return (bool) preg_match('/\/' . $this->regexLeftoverFolders . '\//', $file);
$result = false;
foreach ($this->leftover_folders as $leftover_folder)
{
if (strpos($file, $leftover_folder) !== false)
{
$error_message = JText::_("COM_JEDCHECKER_ERROR_FRAMEWORK_GIT") . ":";
$this->report->addWarning($file, $error_message, 0);
$result = true;
}
}
return $result;
} }
/** /**
@ -111,12 +140,43 @@ class JedcheckerRulesFramework extends JEDcheckerRule
*/ */
protected function find($file) protected function find($file)
{ {
$content = (array) file($file); $origContent = (array) file($file);
if (count($origContent) === 0)
{
return false;
}
$result = false; $result = false;
$content = file_get_contents($file);
// Check BOM
if (strncmp($content, "\xEF\xBB\xBF", 3) === 0)
{
$this->report->addError($file, JText::_('COM_JEDCHECKER_ERROR_FRAMEWORK_BOM_FOUND'));
$result = true;
}
// Clean non-code
$content = 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))
{
$lineno = substr_count($content, "\n", 0, $match[0][1]);
$this->report->addError($file, JText::_('COM_JEDCHECKER_ERROR_FRAMEWORK_SHORT_PHP_TAG'), $lineno + 1, $origContent[$lineno]);
$result = true;
}
// Run other tests
foreach ($this->getTests() as $testObject) foreach ($this->getTests() as $testObject)
{ {
if ($this->runTest($file, $content, $testObject)) if ($this->runTest($file, $origContent, $cleanContent, $testObject))
{ {
$result = true; $result = true;
} }
@ -129,31 +189,52 @@ class JedcheckerRulesFramework extends JEDcheckerRule
* runs tests and reports to the appropriate function if strings match. * runs tests and reports to the appropriate function if strings match.
* *
* @param string $file The file name * @param string $file The file name
* @param array $content The file content * @param array $origContent The file content
* @param array $cleanContent The file content w/o non-code elements
* @param object $testObject The test object generated by getTests() * @param object $testObject The test object generated by getTests()
* *
* @return boolean * @return boolean
*/ */
private function runTest($file, $content, $testObject) private function runTest($file, $origContent, $cleanContent, $testObject)
{ {
// @todo remove as unused?
$error_count = 0; $error_count = 0;
foreach ($content as $line_number => $line) foreach ($cleanContent as $line_number => $line)
{ {
foreach ($testObject->tests AS $singleTest) $origLine = $origContent[$line_number];
foreach ($testObject->tests as $singleTest)
{ {
if (stripos($line, $singleTest) !== false) $regex = preg_quote($singleTest, '/');
// Add word boundary check for rules staring/ending with a letter (to avoid false-positives because of partial match)
if (ctype_alpha($singleTest[0]))
{ {
$line = str_ireplace($singleTest, '<b>' . $singleTest . '</b>', $line); $regex = '\b' . $regex;
$error_message = JText::_('COM_JEDCHECKER_ERROR_FRAMEWORK_' . strtoupper($testObject->group)) . ':<pre>' . $line . '</pre>'; }
if (ctype_alpha($singleTest[strlen($singleTest) - 1]))
{
$regex .= '\b';
}
if (preg_match('/' . $regex . '/i', $line))
{
$origLine = str_ireplace($singleTest, '<b>' . $singleTest . '</b>', htmlspecialchars($origLine));
$error_message = JText::_('COM_JEDCHECKER_ERROR_FRAMEWORK_' . strtoupper($testObject->group)) . ':<pre>' . $origLine . '</pre>';
switch ($testObject->kind) switch ($testObject->kind)
{ {
case 'error':$this->report->addError($file, $error_message, $line_number); case 'error':
$this->report->addError($file, $error_message, $line_number);
break; break;
case 'warning':$this->report->addWarning($file, $error_message, $line_number); case 'warning':
$this->report->addWarning($file, $error_message, $line_number);
break; break;
case 'compatibility':$this->report->addCompat($file, $error_message, $line_number); case 'compatibility':
$this->report->addCompat($file, $error_message, $line_number);
break; break;
default: default:
// Case 'notice': // Case 'notice':
@ -161,6 +242,7 @@ class JedcheckerRulesFramework extends JEDcheckerRule
break; break;
} }
} }
// If you scored 10 errors on a single file, that's enough for now. // If you scored 10 errors on a single file, that's enough for now.
if ($error_count > 10) if ($error_count > 10)
{ {
@ -181,7 +263,7 @@ class JedcheckerRulesFramework extends JEDcheckerRule
* BUT MAKE SURE that you add the relevant key to the translation files: * BUT MAKE SURE that you add the relevant key to the translation files:
* COM_JEDCHECKER_ERROR_NOFRAMEWOR_SOMEKEY * COM_JEDCHECKER_ERROR_NOFRAMEWOR_SOMEKEY
* *
* @return boolean * @return array
*/ */
private function getTests() private function getTests()
{ {