33
2
mirror of https://github.com/joomla-extensions/jedchecker.git synced 2024-12-29 12:52:37 +00:00

Merge pull request #6 from eaxs/master

Added rule and report base class
This commit is contained in:
Daniel Dimitrov 2012-08-04 10:58:23 -07:00
commit b9faf62422
12 changed files with 569 additions and 142 deletions

View File

@ -9,22 +9,44 @@
defined('_JEXEC') or die('Restricted access');
defined('_JEXEC') or die('Restricted access');
jimport('joomla.filesystem');
jimport('joomla.filesystem.archive');
class jedcheckerControllerPolice extends JController {
public function check() {
class jedcheckerControllerPolice extends JController
{
public function check()
{
$rule = JRequest::getString('rule');
JLoader::discover('jedcheckerRules',JPATH_COMPONENT_ADMINISTRATOR . '/libraries/rules/');
// require_once JPATH_COMPONENT_ADMINISTRATOR . '/libraries/rules/'.$rule.'.php';
$path = JFactory::getConfig()->get('tmp_path') . '/jed_checker/unzipped';
$class = 'jedcheckerRules'.ucfirst($rule);
$police = new $class;
$folders = JFolder::folders($path);
$police->check($path.'/'.$folders[0]);
$path = JFactory::getConfig()->get('tmp_path') . '/jed_checker/unzipped';
$class = 'jedcheckerRules'.ucfirst($rule);
// Stop if the class does not exist
if(!class_exists($class)) {
return false;
}
// Prepare rule properties
$folders = JFolder::folders($path);
$properties = array('basedir' => $path.'/'.$folders[0]);
// Create instance of the rule
$police = new $class($properties);
// Perform check
$police->check();
// Get the report and then print it
$report = $police->get('report');
echo '<span class="rule">'
. JText::_('COM_JEDCHECKER_RULE') .' ' . JText::_($police->get('id'))
. ' - '. JText::_($police->get('title'))
. '</span><br/>'
. $report->getHTML();
}
}
}

View File

@ -0,0 +1,10 @@
; This is the configuration file of the HTLM indexes rule.
;
; @author eaxs
; @date 07/06/2012
; @copyright Copyright (C) 2008 - 2012 compojoom.com . All rights reserved.
; @license GNU General Public License version 2 or later; see LICENSE
; Joomla system directories
sysfolders = "administrator, components, language, language/.*, media, modules, plugins, plugins/content, plugins/editors, plugins/editors-xtd, plugins/finder, plugins/search, plugins/system, plugins/user"

View File

@ -1,7 +1,7 @@
<?php
/**
* @author Daniel Dimitrov - compojoom.com
* @date: 02.06.12
* @date: 06.07.12
*
* @copyright Copyright (C) 2008 - 2012 compojoom.com . All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE
@ -9,13 +9,39 @@
defined('_JEXEC') or die('Restricted access');
class jedcheckerRulesHtmlindexes {
// Include the rule base class
require_once(JPATH_COMPONENT_ADMINISTRATOR.'/models/rule.php');
class jedcheckerRulesHtmlindexes extends JEDcheckerRule
{
/**
* The formal ID of this rule. For example: SE1.
*
* @var string
*/
protected $id = 'SE1';
/**
* The title or caption of this rule.
*
* @var string
*/
protected $title = 'COM_JEDCHECKER_RULE_SE1';
/**
* The description of this rule.
*
* @var string
*/
protected $description = 'COM_JEDCHECKER_RULE_SE1_DESC';
public $folders = array();
public $indexes = array();
public function check($startFolder)
public function check()
{
$this->findHtml($startFolder, 1);
$this->findHtml($this->basedir, 1);
/**
* let us "merge" the 2 arrays
@ -23,18 +49,14 @@ class jedcheckerRulesHtmlindexes {
*/
$indexes = array_replace($this->folders, $this->indexes);
echo '<span class="rule">'.JText::_('COM_JEDCHECKER_RULE_SE1') . '</span><br />';
if(count($indexes) && in_array(false, $indexes)) {
foreach($indexes as $key => $index) {
foreach($indexes as $key => $index)
{
if(!$index) {
echo $key . '<br />';
$this->report->addError($key, 'COM_JEDCHECKER_ERROR_HTML_INDEX_NOT_FOUND');
}
}
} else {
echo '<span class="success">'.JText::_('COM_JEDCHECKER_EVERYTHING_SEEMS_TO_BE_FINE_WITH_THAT_RULE').'</span>';
}
}
/**
@ -45,25 +67,12 @@ class jedcheckerRulesHtmlindexes {
*/
public function findHtml($start, $root = 0)
{
// array of system folders (regex)
// will match paths ending with these folders
$system_folders = array(
'administrator',
'components',
'language',
'language/.*',
'media',
'modules',
'plugins',
'plugins/content',
'plugins/editors',
'plugins/editors-xtd',
'plugins/finder',
'plugins/search',
'plugins/system',
'plugins/user'
);
$system_folders = explode(',', $this->params->get('sysfolders'));
// Make sure there are no spaces
array_walk($system_folders, create_function('&$v', '$v = trim($v);'));
$iterator = new DirectoryIterator($start);

View File

@ -0,0 +1,10 @@
; This is the configuration file of the JEXEC rule.
;
; @author eaxs
; @date 07/06/2012
; @copyright Copyright (C) 2008 - 2012 compojoom.com . All rights reserved.
; @license GNU General Public License version 2 or later; see LICENSE
; The valid constants to search for
constants ="_JEXEC, JPATH_PLATFORM, JPATH_BASE, AKEEBAENGINE, WF_EDITOR"

View File

@ -1,7 +1,7 @@
<?php
/**
* @author eaxs
* @date 06/08/2012
* @date 07/06/2012
* @copyright Copyright (C) 2008 - 2012 compojoom.com . All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE
*/
@ -9,52 +9,58 @@
defined('_JEXEC') or die('Restricted access');
// Include the rule base class
require_once(JPATH_COMPONENT_ADMINISTRATOR.'/models/rule.php');
/**
* This class searches all files for the _JEXEC check
* which prevents direct file access.
*
*/
class jedcheckerRulesJexec
class jedcheckerRulesJexec extends JEDcheckerRule
{
/**
* Holds all file names that failed to pass the check
* @var array
* The formal ID of this rule. For example: SE1.
*
* @var string
*/
protected $missing;
protected $id = 'PH2';
/**
* The title or caption of this rule.
*
* @var string
*/
protected $title = 'COM_JEDCHECKER_RULE_PH2';
/**
* The description of this rule.
*
* @var string
*/
protected $description = 'COM_JEDCHECKER_RULE_PH2_DESC';
/**
* Initiates the file search and check
*
* @param string $basedir The base directory of the package to check
* @return void
*/
public function check($basedir)
public function check()
{
$this->missing = array();
$files = JFolder::files($basedir, '.php', true, true);
// Find all php files of the extension
$files = JFolder::files($this->basedir, '.php$', true, true);
// Iterate through all files in the package
// Iterate through all files
foreach($files as $file)
{
// Try to find the _JEXEC check in the file
if(!$this->findJExec($file)) {
$this->missing[] = $file;
if(!$this->find($file)) {
// Add as error to the report if it was not found
$this->report->addError($file, 'COM_JEDCHECKER_ERROR_JEXEC_NOT_FOUND');
}
}
echo '<span class="rule">'.JText::_('COM_JEDCHECKER_RULE_PH2') .'</span><br/>';
if(count($this->missing)) {
// Echo all files which don't have the _JEXEC check
foreach($this->missing AS $file)
{
echo $file.'<br/>';
}
} else {
echo '<span class="success">'.JText::_('COM_JEDCHECKER_EVERYTHING_SEEMS_TO_BE_FINE_WITH_THAT_RULE').'</span>';
}
}
@ -64,36 +70,36 @@ class jedcheckerRulesJexec
* @param string $file The path to the file
* @return boolean True if the statement was found, otherwise False.
*/
protected function findJexec($file)
protected function find($file)
{
$content = (array) file($file);
$defines = array(
'_JEXEC',
'JPATH_PLATFORM',
'JPATH_BASE',
'AKEEBAENGINE',
'WF_EDITOR'
);
// Get the constants to look for
$defines = $this->params->get('constants');
$defines = explode(',', $defines);
foreach($content AS $line)
foreach ($content AS $line)
{
// Search for "defined"
$pos_1 = stripos($line, 'defined');
// Skip the line if "defined" is not found
if ($pos_1 === false) {
continue;
}
// Search for "die".
// "or" may not be present depending on syntax
$pos_3 = stripos($line, 'die');
// Skip the line if "die" is not found
if ($pos_3 === false) {
continue;
}
// Search for the constant name
foreach ($defines AS $define)
{
// Search for "defined"
$pos_1 = stripos($line, 'defined');
// Skip the line if "defined" is not found
if ($pos_1 === false) {
continue;
}
// Search for "die".
// "or" may not be present depending on syntax
$pos_3 = stripos($line, 'die');
// Skip the line if "die" is not found
if ($pos_3 === false) {
continue;
}
$define = trim($define);
// Search for the define
$pos_2 = strpos($line, $define);

View File

@ -1,7 +1,7 @@
<?php
/**
* @author eaxs
* @date 06/26/2012
* @date 07/06/2012
* @copyright Copyright (C) 2008 - 2012 compojoom.com . All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE
*/
@ -9,53 +9,54 @@
defined('_JEXEC') or die('Restricted access');
// Include the rule base class
require_once(JPATH_COMPONENT_ADMINISTRATOR.'/models/rule.php');
/**
* This class searches all xml manifestes for a valid license.
*
*/
class jedcheckerRulesXMLlicense
class jedcheckerRulesXMLlicense extends JEDcheckerRule
{
/**
* Holds all files that failed to pass the check
* @var array
* The formal ID of this rule. For example: SE1.
*
* @var string
*/
protected $missing;
protected $id = 'PH3';
/**
* The title or caption of this rule.
*
* @var string
*/
protected $title = 'COM_JEDCHECKER_RULE_PH3';
/**
* The description of this rule.
*
* @var string
*/
protected $description = 'COM_JEDCHECKER_RULE_PH3_DESC';
/**
* Initiates the search and check
*
* @param string $basedir The base directory of the package to check
* @return void
*/
public function check($basedir)
public function check()
{
$this->missing = array();
$files = JFolder::files($basedir, '.xml$', true, true);
// Find all XML files of the extension
$files = JFolder::files($this->basedir, '.xml$', true, true);
// Iterate through all files in the package
// Iterate through all the xml files
foreach ($files as $file)
{
// Try to find the license in the file
if (!$this->find($file)) {
$this->missing[] = $file;
}
// Try to find the license
$this->find($file);
}
echo '<span class="rule">'.JText::_('COM_JEDCHECKER_RULE_PH3') .'</span><br/>';
// Echo all files which failed the check
if (count($this->missing)) {
foreach ($this->missing AS $file)
{
echo $file.'<br/>';
}
}
else {
echo '<span class="success">'.JText::_('COM_JEDCHECKER_EVERYTHING_SEEMS_TO_BE_FINE_WITH_THAT_RULE').'</span>';
}
}
@ -81,12 +82,16 @@ class jedcheckerRulesXMLlicense
}
// Check if there's a license tag
if (!isset($xml->license)) return false;
if (!isset($xml->license)) {
$this->report->addError($file, 'COM_JEDCHECKER_ERROR_XML_LICENSE_NOT_FOUND');
return false;
}
// Check if the license is gpl
if (stripos($xml->license, 'gpl') === false &&
stripos($xml->license, 'general public license') === false)
{
$this->report->addCompat($file, 'COM_JEDCHECKER_ERROR_XML_LICENSE_NOT_GPL');
return false;
}

View File

@ -0,0 +1 @@
<html><body bgcolor="#FFFFFF"></body></html>

View File

@ -0,0 +1,222 @@
<?php
/**
* @author eaxs
* @date 07/06/2012
* @copyright Copyright (C) 2008 - 2012 compojoom.com . All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE
*/
defined('_JEXEC') or die('Restricted access');
/**
* This class is meant to be used by JED rules to
* create a report.
*
*/
class JEDcheckerReport extends JObject
{
/**
* Contains the report data.
*
* @see reset
* @var array
*/
protected $data;
/**
* The absolute path to the target extension.
*
* @var string
*/
protected $basedir;
/**
* Constructor. Initialises variables.
*
* @param mixed $properties See JObject::__construct
*
* @return void
*/
public function __construct($properties = null)
{
// Construct JObject
parent::__construct($properties);
// Initialise vars
if(empty($this->data)) $this->reset();
}
/**
* Resets the report data.
*
* @return void
*/
public function reset()
{
$this->data = array();
$this->data['errors'] = array();
$this->data['compat'] = array();
$this->data['count'] = new stdClass();
$this->data['count']->total = 0;
$this->data['count']->errors = 0;
$this->data['count']->compat = 0;
}
/**
* Adds an error to the report.
*
* @param string $location The location of the error. Can be a path to a file or dir.
* @param string $text An optional description of the error.
* @param integer $line If $location is a file, you may specify the line where the
* error occured.
*
* @return void
*/
public function addError($location, $text = NULL, $line = 0)
{
$item = new stdClass();
$item->location = $location;
$item->line = $line;
$item->text = (empty($text) ? '' : JText::_($text));
$this->addItem($item, 'errors');
}
/**
* Adds a compatibility issue to the report.
*
* @param string $location The location of the issue. Can be a path to a file or dir.
* @param string $text An optional description of the issue
* @param integer $line If $location is a file, you may specify the line where the
* issue occured.
*
* @return void
*/
public function addCompat($location, $text = NULL, $line = 0)
{
$item = new stdClass();
$item->location = $location;
$item->line = $line;
$item->text = empty($text) ? NULL : JText::_($text);
$this->addItem($item, 'compat');
}
/**
* Formats the existing report data into HTML and returns it.
*
* @return string The HTML report data
*/
public function getHTML()
{
$html = array();
if($this->data['count']->total == 0) {
// No errors or compatibility issues found
$html[] = '<span class="success">';
$html[] = JText::_('COM_JEDCHECKER_EVERYTHING_SEEMS_TO_BE_FINE_WITH_THAT_RULE');
$html[] = '</span>';
}
else {
$error_count = $this->data['count']->errors;
$compat_count = $this->data['count']->compat;
// Go through the error list
if($error_count > 0) {
$html[] = '<strong>'.$error_count. ' '.JText::_('COM_JEDCHECKER_ERRORS').'</strong>';
$html[] = '<ul class="jedchecker-rule-errors">';
foreach($this->data['errors'] AS $i => $item)
{
$num = $i + 1;
// Add the error count number
$html[] = '<li><strong>#'.str_pad($num, 3, '0', STR_PAD_LEFT).':</strong>&nbsp;';
$html[] = $item->location;
// Add line information if given
if($item->line > 0) {
$html[] = ' '.JText::_('COM_JEDCHECKER_IN_LINE').': <strong>'.$item->line.'</strong>';
}
// Add text if given
if(!empty($item->text)) {
$html[] = '<br /><small>'.$item->text.'</small>';
}
$html[] = '</li>';
}
$html[] = '</ul>';
}
// Go through the compat list
if($compat_count > 0) {
$html[] = '<strong>'.$error_count. ' '.JText::_('COM_JEDCHECKER_COMPAT_ISSUES').'</strong>';
$html[] = '<ul class="jedchecker-rule-compat">';
foreach($this->data['compat'] AS $i => $item)
{
$num = $i + 1;
// Add the error count number
$html[] = '<li><p><strong>#'.str_pad($num, 3, '0', STR_PAD_LEFT).'</strong> ';
$html[] = $item->location;
// Add line information if given
if($item->line > 0) {
$html[] = ' '.JText::_('COM_JEDCHECKER_IN_LINE').': <strong>'.$item->line.'</strong>';
}
$html[] = '</p>';
// Add text if given
if(!empty($item->text)) {
$html[] = '<small>'.$item->text.'</small>';
}
$html[] = '</li>';
}
$html[] = '</ul>';
}
}
return implode('', $html);
}
/**
* Adds an item to the report data
*
* @param object $item The item to add.
* @param string $type Optional item type. Can be 'errors' or 'compat'.
* Defaults to 'errors'.
*
* @return void
*/
protected function addItem($item, $type = 'errors')
{
// Remove the base dir from the location
if(!empty($this->basedir)) {
$item->location = str_replace($this->basedir, '', $item->location);
if($item->location == '') $item->location = '/';
}
// Add the item to the report data
$this->data[$type][] = $item;
$this->data['count']->total++;
$this->data['count']->$type++;
}
}

View File

@ -0,0 +1,131 @@
<?php
/**
* @author eaxs
* @date 07/06/2012
* @copyright Copyright (C) 2008 - 2012 compojoom.com . All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE
*/
defined('_JEXEC') or die('Restricted access');
/**
* Serves as a base class for all JED rules.
*
*/
class JEDcheckerRule extends JObject
{
/**
* The formal ID of this rule. For example: SE1.
*
* @var string
*/
protected $id;
/**
* The title or caption of this rule.
*
* @var string
*/
protected $title;
/**
* The description of this rule.
*
* @var string
*/
protected $description;
/**
* The absolute path to the target extension.
*
* @var string
*/
protected $basedir;
/**
* Optional rule parameters.
*
* @var object
*/
protected $params;
/**
* The report summary
*
* @var array
*/
protected $report;
/**
* Constructor. Initialises variables.
*
* @param mixed $properties See JObject::__construct
*
* @return void
*/
public function __construct($properties = null)
{
// Construct JObject
parent::__construct($properties);
// Initialise vars
if(empty($this->report)) {
// Create a new report
require_once (JPATH_COMPONENT_ADMINISTRATOR.'/models/report.php');
$this->report = new JEDcheckerReport($properties);
}
// Try to load the params
if(empty($this->params)) {
$this->params = $this->loadParams();
}
}
/**
* Performs the rule check. This method should be overloaded!
*
*/
public function check()
{
}
/**
* Attempts to load a .ini param file of this rule.
*
* @return JRegistry
*/
protected function loadParams()
{
// Try to determine the name and location of the params file
$file_name = str_replace('jedcheckerrules', '', strtolower(get_class($this)));
$params_file = JPATH_COMPONENT_ADMINISTRATOR.'/libraries/rules/'.$file_name.'.ini';
$params = JRegistry::getInstance('jedchecker.rule.'.$file_name);
// Load the params from the ini file
if (file_exists($params_file)) {
// Due to a bug in Joomla 2.5.6, this method cannot be used
//$params->loadFile($params_file, 'INI');
// Get the contents of the file
jimport('joomla.filesystem.file');
$data = JFile::read($params_file);
if($data) {
$obj = (object) parse_ini_string($data);
if(is_object($obj)) {
$params->loadObject($obj);
}
}
}
return $params;
}
}

View File

@ -77,26 +77,25 @@ JHtml::script('media/com_jedchecker/js/police.js');
<?php echo JText::_('COM_JEDCHECKER_HOW_TO_INTERPRET_RESULTS'); ?>
</h2>
<ul>
<li>
<p>
<span class="rule"><?php echo JText::_('COM_JEDCHECKER_RULE_SE1'); ?></span><br />
<?php echo JText::_('COM_JEDCHECKER_RULE_SE1_DESC'); ?>
</p>
</li>
<li>
<p>
<span class="rule"><?php echo JText::_('COM_JEDCHECKER_RULE_PH2'); ?></span><br />
<?php echo JText::_('COM_JEDCHECKER_RULE_PH2_DESC'); ?>
<?php
foreach($this->jsOptions['rules'] AS $rule)
{
$class = 'jedcheckerRules'.ucfirst($rule);
</p>
</li>
<li>
<p>
<span class="rule"><?php echo JText::_('COM_JEDCHECKER_RULE_PH3'); ?></span><br />
<?php echo JText::_('COM_JEDCHECKER_RULE_PH3_DESC'); ?>
</p>
</li>
if(!class_exists($class)) continue;
$rule = new $class();
?>
<li>
<p>
<span class="rule">
<?php echo JText::_('COM_JEDCHECKER_RULE').' '.$rule->get('id').' - '.JText::_($rule->get('title'));?>
</span>
<p><?php echo JText::_($rule->get('description')); ?></p>
</p>
</li>
<?php
}
?>
</ul>
</div>
</div>

View File

@ -24,11 +24,15 @@ class jedcheckerViewUploads extends JView
public function getRules()
{
$exclude = array('.svn', 'CVS', '.DS_Store', '__MACOSX', 'index.html');
$files = JFolder::files(JPATH_COMPONENT_ADMINISTRATOR . '/libraries/rules', '.', false, false, $exclude);
foreach ($files as $file) {
$rules[] = str_replace('.php', '', $file);
$rules = array();
$files = JFolder::files(JPATH_COMPONENT_ADMINISTRATOR . '/libraries/rules', '.php$', false, false);
JLoader::discover('jedcheckerRules',JPATH_COMPONENT_ADMINISTRATOR . '/libraries/rules/');
foreach ($files as $file)
{
$rules[] = substr($file, 0, -4);
}
return $rules;
}

View File

@ -11,12 +11,20 @@ COM_JEDCHECKER_STEP3="Click on check and review the results"
COM_JEDCHECKER_WALL_OF_HONOR="Wall of honor"
COM_JEDCHECKER_PEOPLE_THAT_HAVE_HELPED_WITH_THE_DEVELOPMENT="People that have helped with the development of this component"
COM_JEDCHECKER_HOW_TO_INTERPRET_RESULTS="How to interpret the results?"
COM_JEDCHECKER_RULE_SE1="Rule SE1 - Extension is missing index.html file in all folders"
COM_JEDCHECKER_RULE_SE1="Extension is missing index.html file in all folders"
COM_JEDCHECKER_RULE_SE1_DESC="If you want your extension to be listed on the JED, then you should make sure that all your extension folders contain an index.html file. - Developers don't like this rule at all - it fills your package with index.html files, which in terms slows down the installation process etc. But index.html files provide protection for badly configured hosts (one could argue if we need to try to do anything for those), but as long the joomla CMS comes with those files the JED is going to require that extensions also have those."
COM_JEDCHECKER_RULE_PH2="Rule PH2 - PHP Files missing JEXEC security"
COM_JEDCHECKER_RULE_PH2="PHP Files missing JEXEC security"
COM_JEDCHECKER_RULE_PH2_DESC="All the PHP files in your extension needs to have a defined('_JEXEC') or die(); statement in the beginning of each file. This ensures that the file cannot be opened outside of the joomla installation and this way increases the security of your site."
COM_JEDCHECKER_RULE_PH3="Rule PH3 - License tag missing or incorrect in XML install file"
COM_JEDCHECKER_RULE_PH3="License tag missing or incorrect in XML install file"
COM_JEDCHECKER_RULE_PH3_DESC="An install file should include the license information in a license-tag. The license must be GPL or GPL compatible."
COM_JEDCHECKER_EVERYTHING_SEEMS_TO_BE_FINE_WITH_THAT_RULE="Congrats! Everything seems to be fine with that rule!"
COM_JEDCHECKER_DEVELOPED_BY="JEDchecker is primary developed by <a href='%s'>compojoom.com</a>"
COM_JEDCHECKER_PHP_VERSION_INCOMPATIBLE="JEDchecker is incompatible with the PHP version that you run on this site: %s. You would need at least PHP Version %s. Aborting installation"
COM_JEDCHECKER_ERROR_HTML_INDEX_NOT_FOUND="Missing index.html in this directory."
COM_JEDCHECKER_ERROR_JEXEC_NOT_FOUND="The JEXEC security check was not found in this file."
COM_JEDCHECKER_ERROR_XML_LICENSE_NOT_FOUND="No license tag was found in this XML file."
COM_JEDCHECKER_ERROR_XML_LICENSE_NOT_GPL="Please check if the license in this file is compatible with the GPL."
COM_JEDCHECKER_RULE="Rule"
COM_JEDCHECKER_ERRORS="Errors"
COM_JEDCHECKER_COMPAT_ISSUES="Compatibility Issues"
COM_JEDCHECKER_IN_LINE="in line"