From 8e53d6f9646ac0fa90156999f062970e0bedcdac Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Tue, 11 May 2021 21:19:44 +0300 Subject: [PATCH 01/13] extract extension's language file loading into function loadExtensionLanguage --- .../libraries/rules/xmlinfo.php | 225 ++++++++++-------- 1 file changed, 120 insertions(+), 105 deletions(-) diff --git a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php index b0355df..3b7dc8b 100644 --- a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php +++ b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php @@ -120,114 +120,11 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule // Get extension type $type = (string) $xml['type']; - // Get extension's element name (simulates work of Joomla's installer) - - // Firstly, check for node - if (isset($xml->element)) - { - $extension = (string) $xml->element; - } - else - { - // Otherwise, use node or plugin/module attribute in the section - $extension = (string) $xml->name; - - if (isset($xml->files)) - { - foreach ($xml->files->children() as $child) - { - if (isset($child[$type])) - { - $extension = (string) $child[$type]; - } - } - } - } - - // Filter extension's element name - $extension = strtolower(JFilterInput::getInstance()->clean($extension, 'cmd')); - - // Component's element name starts with com_ - if ($type === 'component' && strpos($extension, 'com_') !== 0) - { - $extension = 'com_' . $extension; - } - - // Plugin's element name starts with plg_ - if ($type === 'plugin' && isset($xml['group']) && strpos($extension, 'plg_') !== 0) - { - $extension = 'plg_' . $xml['group'] . '_' . $extension; - } - // Load the language of the extension (if any) - $lang = JFactory::getLanguage(); - - // Search for .sys.ini translation file - $langDir = dirname($file); - $langTag = 'en-GB'; // $lang->getDefault(); - - // Populate list of directories to look for - $lookupLangDirs = array(); - - if (isset($xml->administration->files['folder'])) - { - $lookupLangDirs[] = trim($xml->administration->files['folder'], '/') . '/language/' . $langTag; - } - - if (isset($xml->files['folder'])) - { - $lookupLangDirs[] = trim($xml->files['folder'], '/') . '/language/' . $langTag; - } - - $lookupLangDirs[] = 'language/' . $langTag; - - if (isset($xml->administration->languages)) - { - $folder = trim($xml->administration->languages['folder'], '/'); - - foreach ($xml->administration->languages->language as $language) - { - if (trim($language['tag']) === $langTag) - { - $lookupLangDirs[] = trim($folder . '/' . dirname($language), '/'); - } - } - } - - if (isset($xml->languages)) - { - $folder = trim($xml->languages['folder'], '/'); - - foreach ($xml->languages->language as $language) - { - if (trim($language['tag']) === $langTag) - { - $lookupLangDirs[] = trim($folder . '/' . dirname($language), '/'); - } - } - } - - $lookupLangDirs[] = ''; - - $lookupLangDirs = array_unique($lookupLangDirs); - - // Looking for language file in specified directories - foreach ($lookupLangDirs as $dir) - { - $langSysFile = - $langDir . '/' . - ($dir === '' ? '' : $dir . '/') . - $langTag. '.' . $extension . '.sys.ini'; - if (is_file($langSysFile)) - { - $loadLanguage = new ReflectionMethod($lang, 'loadLanguage'); - $loadLanguage->setAccessible(true); - $loadLanguage->invoke($lang, $langSysFile, $extension); - break; - } - } + $this->loadExtensionLanguage($xml, dirname($file)); // Get the real extension's name now that the language has been loaded + $lang = JFactory::getLanguage(); $extensionName = $lang->_((string) $xml->name); $info[] = JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_XML', $extensionName); @@ -301,6 +198,124 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule return true; } + /** + * Locate and load extension's .sys.ini translation file + * + * @param SimpleXMLElement $xml Extension's XML manifest + * @param string $langDir The basepath + * @param string $langTag The language to load + * + * @return void + * @since 3.0 + */ + protected function loadExtensionLanguage($xml, $langDir, $langTag = 'en-GB') + { + $type = (string) $xml['type']; + + // Get extension's element name (simulates work of Joomla's installer) + + // Firstly, check for node + if (isset($xml->element)) + { + $extension = (string) $xml->element; + } + else + { + // Otherwise, use node or plugin/module attribute in the section + $extension = (string) $xml->name; + + if (isset($xml->files)) + { + foreach ($xml->files->children() as $child) + { + if (isset($child[$type])) + { + $extension = (string) $child[$type]; + } + } + } + } + + // Filter extension's element name + $extension = strtolower(JFilterInput::getInstance()->clean($extension, 'cmd')); + + // Component's element name starts with com_ + if ($type === 'component' && strpos($extension, 'com_') !== 0) + { + $extension = 'com_' . $extension; + } + + // Plugin's element name starts with plg_ + if ($type === 'plugin' && isset($xml['group']) && strpos($extension, 'plg_') !== 0) + { + $extension = 'plg_' . $xml['group'] . '_' . $extension; + } + + // Load the language of the extension (if any) + $lang = JFactory::getLanguage(); + + // Populate list of directories to look for + $lookupLangDirs = array(); + + if (isset($xml->administration->files['folder'])) + { + $lookupLangDirs[] = trim($xml->administration->files['folder'], '/') . '/language/' . $langTag; + } + + if (isset($xml->files['folder'])) + { + $lookupLangDirs[] = trim($xml->files['folder'], '/') . '/language/' . $langTag; + } + + $lookupLangDirs[] = 'language/' . $langTag; + + if (isset($xml->administration->languages)) + { + $folder = trim($xml->administration->languages['folder'], '/'); + + foreach ($xml->administration->languages->language as $language) + { + if (trim($language['tag']) === $langTag) + { + $lookupLangDirs[] = trim($folder . '/' . dirname($language), '/'); + } + } + } + + if (isset($xml->languages)) + { + $folder = trim($xml->languages['folder'], '/'); + + foreach ($xml->languages->language as $language) + { + if (trim($language['tag']) === $langTag) + { + $lookupLangDirs[] = trim($folder . '/' . dirname($language), '/'); + } + } + } + + $lookupLangDirs[] = ''; + + $lookupLangDirs = array_unique($lookupLangDirs); + + // Looking for language file in specified directories + foreach ($lookupLangDirs as $dir) + { + $langSysFile = + $langDir . '/' . + ($dir === '' ? '' : $dir . '/') . + $langTag. '.' . $extension . '.sys.ini'; + if (is_file($langSysFile)) + { + $loadLanguage = new ReflectionMethod($lang, 'loadLanguage'); + $loadLanguage->setAccessible(true); + $loadLanguage->invoke($lang, $langSysFile, $extension); + break; + } + } + } + /** * Check domain name contains "Joomla"/derivative * From 4ac26c9282ef7cd03c973d72fa1d496915a669fe Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Tue, 11 May 2021 23:07:22 +0300 Subject: [PATCH 02/13] check reserved words --- .../language/en-GB/en-GB.com_jedchecker.ini | 3 +-- .../com_jedchecker/libraries/rules/xmlinfo.php | 11 +++-------- 2 files changed, 4 insertions(+), 10 deletions(-) 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 bff09a4..13b3220 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 @@ -45,8 +45,7 @@ COM_JEDCHECKER_INFO_XML_NAME_XML="The name tag in this file is: %s" COM_JEDCHECKER_INFO_XML_VERSION_XML="Version tag has the value: %s" COM_JEDCHECKER_INFO_XML_CREATIONDATE_XML="The creationDate tag has the value: %s" COM_JEDCHECKER_INFO_XML_NO_MANIFEST="No manifest file found" -COM_JEDCHECKER_INFO_XML_NAME_MODULE_PLUGIN="Listing name ('%s') contains 'module' or 'plugin'" -COM_JEDCHECKER_INFO_XML_NAME_RESERVED_KEYWORDS="Keywords such as module, plugin or template are considered reserved words and can't be used in the extension names ('%s')" +COM_JEDCHECKER_INFO_XML_NAME_RESERVED_KEYWORDS="Keywords such as module, plugin or template are considered reserved words ('%2$s') and can't be used in the extension names ('%1$s')" COM_JEDCHECKER_INFO_XML_NAME_VERSION="Version in name/title ('%s')" COM_JEDCHECKER_INFO_XML_NAME_JOOMLA="An extension name ('%s') can't start with the word 'Joomla'" COM_JEDCHECKER_INFO_XML_NAME_JOOMLA_DERIVATIVE="Extensions that use 'Joomla' or a derivative of Joomla in the extension name ('%s') need to be licensed by OSM" diff --git a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php index 3b7dc8b..45e4958 100644 --- a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php +++ b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php @@ -134,15 +134,10 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule $this->report->addInfo($file, implode('
', $info)); // NM3 - Listing name contains “module” or “plugin” - if (preg_match('/module|plugin/i', $extensionName)) + // (and other reserved words) + if (preg_match('/\b(?:module|plugin|component|template|extension|free)\b/i', $extensionName, $match)) { - $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_MODULE_PLUGIN', $extensionName)); - } - - // The "template" is reserved keyword - if (stripos($extensionName, 'template') !== false) - { - $this->report->addWarning($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_RESERVED_KEYWORDS', $extensionName)); + $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_RESERVED_KEYWORDS', $extensionName, strtolower($match[0]))); } // NM5 - Version in name/title From 084367bc780b7bdc1957f8cbf59af931edac0456 Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Tue, 11 May 2021 23:08:21 +0300 Subject: [PATCH 03/13] check prefixed names --- .../com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini | 1 + .../components/com_jedchecker/libraries/rules/xmlinfo.php | 6 ++++++ 2 files changed, 7 insertions(+) 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 13b3220..3fd6930 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 @@ -46,6 +46,7 @@ COM_JEDCHECKER_INFO_XML_VERSION_XML="Version tag has the value: %s" COM_JEDCHECKER_INFO_XML_CREATIONDATE_XML="The creationDate tag has the value: %s" COM_JEDCHECKER_INFO_XML_NO_MANIFEST="No manifest file found" COM_JEDCHECKER_INFO_XML_NAME_RESERVED_KEYWORDS="Keywords such as module, plugin or template are considered reserved words ('%2$s') and can't be used in the extension names ('%1$s')" +COM_JEDCHECKER_INFO_XML_NAME_PREFIXED="Listing name ('%s') starts with extension type prefix" COM_JEDCHECKER_INFO_XML_NAME_VERSION="Version in name/title ('%s')" COM_JEDCHECKER_INFO_XML_NAME_JOOMLA="An extension name ('%s') can't start with the word 'Joomla'" COM_JEDCHECKER_INFO_XML_NAME_JOOMLA_DERIVATIVE="Extensions that use 'Joomla' or a derivative of Joomla in the extension name ('%s') need to be licensed by OSM" diff --git a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php index 45e4958..e5c88a7 100644 --- a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php +++ b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php @@ -140,6 +140,12 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_RESERVED_KEYWORDS', $extensionName, strtolower($match[0]))); } + // Extension name shouldn't start with extension type prefix + if (preg_match('/^\s*(?:mod|com|plg|tpl|pkg)_/i', $extensionName)) + { + $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_PREFIXED', $extensionName)); + } + // NM5 - Version in name/title if (preg_match('/(?:\bversion\b|\d\.\d)/i', $extensionName)) { From 0dd8b4e572146fb41662f503ac2b150700a5ced5 Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Tue, 11 May 2021 23:11:15 +0300 Subject: [PATCH 04/13] Allow trailing "for Joomla" in the listing name --- .../language/en-GB/en-GB.com_jedchecker.ini | 4 ++-- .../com_jedchecker/libraries/rules/xmlinfo.php | 14 +++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) 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 3fd6930..0498d92 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 @@ -49,8 +49,8 @@ COM_JEDCHECKER_INFO_XML_NAME_RESERVED_KEYWORDS="Keywords such as module, plugin COM_JEDCHECKER_INFO_XML_NAME_PREFIXED="Listing name ('%s') starts with extension type prefix" COM_JEDCHECKER_INFO_XML_NAME_VERSION="Version in name/title ('%s')" COM_JEDCHECKER_INFO_XML_NAME_JOOMLA="An extension name ('%s') can't start with the word 'Joomla'" -COM_JEDCHECKER_INFO_XML_NAME_JOOMLA_DERIVATIVE="Extensions that use 'Joomla' or a derivative of Joomla in the extension name ('%s') need to be licensed by OSM" -COM_JEDCHECKER_INFO_XML_URL_JOOMLA_DERIVATIVE="Domain names that use 'Joomla' or a derivative of Joomla ('%1$s') need to be licensed by OSM. Please, check your domain name is listed on the Joomla! Trademark Approval Registry page." +COM_JEDCHECKER_INFO_XML_NAME_JOOMLA_DERIVATIVE="Extensions that use 'Joomla' or a derivative of Joomla! in the extension name ('%s') need to be licensed by OSM" +COM_JEDCHECKER_INFO_XML_URL_JOOMLA_DERIVATIVE="Domain names that use 'Joomla' or a derivative of Joomla! ('%1$s') need to be licensed by OSM. Please, check your domain name is listed on the Joomla! Trademark Approval Registry page." COM_JEDCHECKER_INFO_XML_NAME_ADMIN_MENU="The admin menu name '%1$s' isn't the same as the extension name '%2$s'" COM_JEDCHECKER_INFO_XML_NAME_PLUGIN_FORMAT="The name of the plugin ('%s') must comply with the JED naming conventions in the form '{Type} - {Extension Name}'" COM_JEDCHECKER_RULE_PH1="PHP Headers missing GPL License Notice" diff --git a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php index e5c88a7..feafacb 100644 --- a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php +++ b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php @@ -152,15 +152,23 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_VERSION', $extensionName)); } + // Check for "Joomla" in the name if (stripos($extensionName, 'joomla') === 0) { // An extension name can't start with the word "Joomla" $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_JOOMLA', $extensionName)); } - elseif (stripos($extensionName, 'joom') !== false) + else { - // Extensions that use "Joomla" or a derivative of Joomla in the extension name need to be licensed by OSM - $this->report->addWarning($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_JOOMLA_DERIVATIVE', $extensionName)); + $cleanName = preg_replace('/\s+for\s+Joomla!?$/', '', $extensionName); + + if (stripos($cleanName, 'joom') !== false) + { + // Extensions that use "Joomla" or a derivative of Joomla in the extension name need to be licensed by OSM + $this->report->addWarning($file, + JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_JOOMLA_DERIVATIVE', $extensionName, 'https://tm.joomla.org/approved-domains.html') + ); + } } $this->validateDomain($file, (string) $xml->authorUrl); From 10a9cba326b485615c98761ea9c2c663a7c88cfb Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Tue, 11 May 2021 23:25:06 +0300 Subject: [PATCH 05/13] Error for non-ASCII characters in the listing name --- .../com_jedchecker/language/en-GB/en-GB.com_jedchecker.ini | 1 + .../components/com_jedchecker/libraries/rules/xmlinfo.php | 6 ++++++ 2 files changed, 7 insertions(+) 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 0498d92..b8c016e 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 @@ -50,6 +50,7 @@ COM_JEDCHECKER_INFO_XML_NAME_PREFIXED="Listing name ('%s') starts with extension COM_JEDCHECKER_INFO_XML_NAME_VERSION="Version in name/title ('%s')" COM_JEDCHECKER_INFO_XML_NAME_JOOMLA="An extension name ('%s') can't start with the word 'Joomla'" COM_JEDCHECKER_INFO_XML_NAME_JOOMLA_DERIVATIVE="Extensions that use 'Joomla' or a derivative of Joomla! in the extension name ('%s') need to be licensed by OSM" +COM_JEDCHECKER_INFO_XML_NAME_NON_ASCII="Listing name ('%s') contains non-ASCII characters" COM_JEDCHECKER_INFO_XML_URL_JOOMLA_DERIVATIVE="Domain names that use 'Joomla' or a derivative of Joomla! ('%1$s') need to be licensed by OSM. Please, check your domain name is listed on the Joomla! Trademark Approval Registry page." COM_JEDCHECKER_INFO_XML_NAME_ADMIN_MENU="The admin menu name '%1$s' isn't the same as the extension name '%2$s'" COM_JEDCHECKER_INFO_XML_NAME_PLUGIN_FORMAT="The name of the plugin ('%s') must comply with the JED naming conventions in the form '{Type} - {Extension Name}'" diff --git a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php index feafacb..de3ce29 100644 --- a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php +++ b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php @@ -171,6 +171,12 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule } } + // Check extension name consists of ASCII characters only + if (preg_match('/[^\x20-\x7E]/', $extensionName)) + { + $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_NON_ASCII', $extensionName)); + } + $this->validateDomain($file, (string) $xml->authorUrl); if ($type === 'package' && (string) $xml->packagerurl !== (string) $xml->authorUrl) From 30c9ced67ba427d236dade6c71a7c76fa3190f24 Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Mon, 10 May 2021 20:13:28 +0300 Subject: [PATCH 06/13] Check length of the listing name (warning for 40+, error for 80+) --- .../language/en-GB/en-GB.com_jedchecker.ini | 1 + .../com_jedchecker/libraries/rules/xmlinfo.php | 12 ++++++++++++ 2 files changed, 13 insertions(+) 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 b8c016e..0c5e9bb 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 @@ -52,6 +52,7 @@ COM_JEDCHECKER_INFO_XML_NAME_JOOMLA="An extension name ('%s') can't start with t COM_JEDCHECKER_INFO_XML_NAME_JOOMLA_DERIVATIVE="Extensions that use 'Joomla' or a derivative of Joomla! in the extension name ('%s') need to be licensed by OSM" COM_JEDCHECKER_INFO_XML_NAME_NON_ASCII="Listing name ('%s') contains non-ASCII characters" COM_JEDCHECKER_INFO_XML_URL_JOOMLA_DERIVATIVE="Domain names that use 'Joomla' or a derivative of Joomla! ('%1$s') need to be licensed by OSM. Please, check your domain name is listed on the Joomla! Trademark Approval Registry page." +COM_JEDCHECKER_INFO_XML_NAME_TOO_LONG="Listing name ('%s') is too long, consider to shorten it" COM_JEDCHECKER_INFO_XML_NAME_ADMIN_MENU="The admin menu name '%1$s' isn't the same as the extension name '%2$s'" COM_JEDCHECKER_INFO_XML_NAME_PLUGIN_FORMAT="The name of the plugin ('%s') must comply with the JED naming conventions in the form '{Type} - {Extension Name}'" COM_JEDCHECKER_RULE_PH1="PHP Headers missing GPL License Notice" diff --git a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php index de3ce29..343b485 100644 --- a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php +++ b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php @@ -177,6 +177,18 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_NON_ASCII', $extensionName)); } + // Extension name shouldn't be too long + $nameLen = strlen($extensionName); + + if ($nameLen > 80) + { + $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_TOO_LONG', $extensionName)); + } + elseif ($nameLen > 40) + { + $this->report->addWarning($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_TOO_LONG', $extensionName)); + } + $this->validateDomain($file, (string) $xml->authorUrl); if ($type === 'package' && (string) $xml->packagerurl !== (string) $xml->authorUrl) From 758fcf5b370ad70b0ceb87e97c64567c88b9ea24 Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Tue, 11 May 2021 23:29:59 +0300 Subject: [PATCH 07/13] switch to use of JEDCheckerHelper in xmlinfo --- .../libraries/rules/xmlinfo.php | 37 +++---------------- 1 file changed, 5 insertions(+), 32 deletions(-) diff --git a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php index 343b485..31f5d9c 100644 --- a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php +++ b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php @@ -16,6 +16,9 @@ defined('_JEXEC') or die('Restricted access'); // Include the rule base class require_once JPATH_COMPONENT_ADMINISTRATOR . '/models/rule.php'; +// Include the helper class +require_once JPATH_COMPONENT_ADMINISTRATOR . '/libraries/helper.php'; + /** * class JedcheckerRulesXMLinfo @@ -237,40 +240,10 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule */ protected function loadExtensionLanguage($xml, $langDir, $langTag = 'en-GB') { - $type = (string) $xml['type']; - // Get extension's element name (simulates work of Joomla's installer) + $extension = JEDCheckerHelper::getElementName($xml); - // Firstly, check for node - if (isset($xml->element)) - { - $extension = (string) $xml->element; - } - else - { - // Otherwise, use node or plugin/module attribute in the section - $extension = (string) $xml->name; - - if (isset($xml->files)) - { - foreach ($xml->files->children() as $child) - { - if (isset($child[$type])) - { - $extension = (string) $child[$type]; - } - } - } - } - - // Filter extension's element name - $extension = strtolower(JFilterInput::getInstance()->clean($extension, 'cmd')); - - // Component's element name starts with com_ - if ($type === 'component' && strpos($extension, 'com_') !== 0) - { - $extension = 'com_' . $extension; - } + $type = (string) $xml['type']; // Plugin's element name starts with plg_ if ($type === 'plugin' && isset($xml['group']) && strpos($extension, 'plg_') !== 0) From 469a89a434ff07b220628a23ea1f8a3c22dc82c9 Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Tue, 11 May 2021 23:31:22 +0300 Subject: [PATCH 08/13] Joomla code-style fix --- .../components/com_jedchecker/libraries/rules/xmlinfo.php | 1 + 1 file changed, 1 insertion(+) diff --git a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php index 31f5d9c..053710c 100644 --- a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php +++ b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php @@ -323,6 +323,7 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule * @param string $url URL to validate * * @return void + * @since 3.0 */ protected function validateDomain($file, $url) { From bd9b9bb0edd1835b6ee5117301f57023b05cb37f Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Tue, 11 May 2021 23:32:32 +0300 Subject: [PATCH 09/13] add comment line --- .../components/com_jedchecker/libraries/rules/xmlinfo.php | 1 + 1 file changed, 1 insertion(+) diff --git a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php index 053710c..47ad1cf 100644 --- a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php +++ b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php @@ -192,6 +192,7 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule $this->report->addWarning($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_TOO_LONG', $extensionName)); } + // Validate URLs $this->validateDomain($file, (string) $xml->authorUrl); if ($type === 'package' && (string) $xml->packagerurl !== (string) $xml->authorUrl) From 907bbd1d759a84ecc7c41bc858c2785ec15d68f5 Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Tue, 11 May 2021 23:33:20 +0300 Subject: [PATCH 10/13] switch to JEDCheckerHelper::findManifests --- .../components/com_jedchecker/libraries/rules/xmlinfo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php index 47ad1cf..66c6879 100644 --- a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php +++ b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php @@ -70,7 +70,7 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule public function check() { // Find all XML files of the extension - $files = JFolder::files($this->basedir, '\.xml$', true, true); + $files = JEDCheckerHelper::findManifests($this->basedir); $manifestFound = false; From c50e39e357f13b7b9fbb25233fe8fba8c7309ffc Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Mon, 17 May 2021 23:42:59 +0300 Subject: [PATCH 11/13] Apply naming rules to the main manifest file(s?) only (others are checked for URLs, ASCII, length, and menu name only) --- .../libraries/rules/xmlinfo.php | 123 ++++++++++-------- 1 file changed, 67 insertions(+), 56 deletions(-) diff --git a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php index 66c6879..60848c6 100644 --- a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php +++ b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php @@ -74,13 +74,20 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule $manifestFound = false; - // Iterate through all the xml files - foreach ($files as $file) + if (count($files)) { - // Try to find the license - if ($this->find($file)) + $topLevelDepth = substr_count($files[0], '/'); + + // Iterate through all the xml files + foreach ($files as $file) { - $manifestFound = true; + $isTopLevel = substr_count($file, '/') === $topLevelDepth; + + // Try to find the license + if ($this->find($file, $isTopLevel)) + { + $manifestFound = true; + } } } @@ -93,11 +100,12 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule /** * Reads a file and searches for the license * - * @param string $file - The path to the file + * @param string $file - The path to the file + * @param bool $isTopLevel - Is the file located in the top-level manifests directory? * * @return boolean True if the manifest file was found, otherwise False. */ - protected function find($file) + protected function find($file, $isTopLevel) { $xml = JFactory::getXml($file); @@ -136,60 +144,63 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule $this->report->addInfo($file, implode('
', $info)); - // NM3 - Listing name contains “module” or “plugin” - // (and other reserved words) - if (preg_match('/\b(?:module|plugin|component|template|extension|free)\b/i', $extensionName, $match)) + if ($isTopLevel) { - $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_RESERVED_KEYWORDS', $extensionName, strtolower($match[0]))); - } - - // Extension name shouldn't start with extension type prefix - if (preg_match('/^\s*(?:mod|com|plg|tpl|pkg)_/i', $extensionName)) - { - $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_PREFIXED', $extensionName)); - } - - // NM5 - Version in name/title - if (preg_match('/(?:\bversion\b|\d\.\d)/i', $extensionName)) - { - $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_VERSION', $extensionName)); - } - - // Check for "Joomla" in the name - if (stripos($extensionName, 'joomla') === 0) - { - // An extension name can't start with the word "Joomla" - $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_JOOMLA', $extensionName)); - } - else - { - $cleanName = preg_replace('/\s+for\s+Joomla!?$/', '', $extensionName); - - if (stripos($cleanName, 'joom') !== false) + // NM3 - Listing name contains “module” or “plugin” + // (and other reserved words) + if (preg_match('/\b(?:module|plugin|component|template|extension|free)\b/i', $extensionName, $match)) { - // Extensions that use "Joomla" or a derivative of Joomla in the extension name need to be licensed by OSM - $this->report->addWarning($file, - JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_JOOMLA_DERIVATIVE', $extensionName, 'https://tm.joomla.org/approved-domains.html') - ); + $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_RESERVED_KEYWORDS', $extensionName, strtolower($match[0]))); } - } - // Check extension name consists of ASCII characters only - if (preg_match('/[^\x20-\x7E]/', $extensionName)) - { - $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_NON_ASCII', $extensionName)); - } + // Extension name shouldn't start with extension type prefix + if (preg_match('/^\s*(?:mod|com|plg|tpl|pkg)_/i', $extensionName)) + { + $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_PREFIXED', $extensionName)); + } - // Extension name shouldn't be too long - $nameLen = strlen($extensionName); + // NM5 - Version in name/title + if (preg_match('/(?:\bversion\b|\d\.\d)/i', $extensionName)) + { + $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_VERSION', $extensionName)); + } - if ($nameLen > 80) - { - $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_TOO_LONG', $extensionName)); - } - elseif ($nameLen > 40) - { - $this->report->addWarning($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_TOO_LONG', $extensionName)); + // Check for "Joomla" in the name + if (stripos($extensionName, 'joomla') === 0) + { + // An extension name can't start with the word "Joomla" + $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_JOOMLA', $extensionName)); + } + else + { + $cleanName = preg_replace('/\s+for\s+Joomla!?$/', '', $extensionName); + + if (stripos($cleanName, 'joom') !== false) + { + // Extensions that use "Joomla" or a derivative of Joomla in the extension name need to be licensed by OSM + $this->report->addWarning($file, + JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_JOOMLA_DERIVATIVE', $extensionName, 'https://tm.joomla.org/approved-domains.html') + ); + } + } + + // Check extension name consists of ASCII characters only + if (preg_match('/[^\x20-\x7E]/', $extensionName)) + { + $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_NON_ASCII', $extensionName)); + } + + // Extension name shouldn't be too long + $nameLen = strlen($extensionName); + + if ($nameLen > 80) + { + $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_TOO_LONG', $extensionName)); + } + elseif ($nameLen > 40) + { + $this->report->addWarning($file, JText::sprintf('COM_JEDCHECKER_INFO_XML_NAME_TOO_LONG', $extensionName)); + } } // Validate URLs @@ -210,7 +221,7 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule } } - if ($type === 'plugin') + if ($isTopLevel && $type === 'plugin') { // The name of your plugin must comply with the JED naming conventions - plugins in the form “{Type} - {Extension Name}”. $parts = explode(' - ', $extensionName, 2); From e5c59dc116f90e6b4b62058b7e5c2b1c928521c7 Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Sat, 26 Jun 2021 22:08:42 +0300 Subject: [PATCH 12/13] remove incorrect since tags --- .../components/com_jedchecker/libraries/rules/xmlinfo.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php index 60848c6..d8416be 100644 --- a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php +++ b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php @@ -248,7 +248,6 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule * @param string $langTag The language to load * * @return void - * @since 3.0 */ protected function loadExtensionLanguage($xml, $langDir, $langTag = 'en-GB') { @@ -335,7 +334,6 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule * @param string $url URL to validate * * @return void - * @since 3.0 */ protected function validateDomain($file, $url) { From 31bb24d1dd4349f56323f9b5f4d32fe4ab2b9156 Mon Sep 17 00:00:00 2001 From: Denis Ryabov Date: Sun, 27 Jun 2021 00:27:14 +0300 Subject: [PATCH 13/13] add check for allowed extension type (moved here from XMLManifest rules) --- .../com_jedchecker/libraries/rules/xmlinfo.php | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php index d8416be..6e5ed6e 100644 --- a/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php +++ b/administrator/components/com_jedchecker/libraries/rules/xmlinfo.php @@ -50,6 +50,15 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule */ protected $description = 'COM_JEDCHECKER_INFO_XML_DESC'; + /** + * List of JED extension types + * + * @var string[] + */ + protected $jedTypes = array( + 'component', 'module', 'package', 'plugin' + ); + /** * Mapping of the plugin title prefix to the plugin group * @@ -146,6 +155,12 @@ class JedcheckerRulesXMLinfo extends JEDcheckerRule if ($isTopLevel) { + // JED allows components, modules, plugins, and packages (as a container) only + if (!in_array($type, $this->jedTypes, true)) + { + $this->report->addError($file, JText::sprintf('COM_JEDCHECKER_MANIFEST_TYPE_NOT_ACCEPTED', $type)); + } + // NM3 - Listing name contains “module” or “plugin” // (and other reserved words) if (preg_match('/\b(?:module|plugin|component|template|extension|free)\b/i', $extensionName, $match))