diff --git a/administrator/components/com_admin/script.php b/administrator/components/com_admin/script.php index 728217ed3e31a..de208a82be753 100644 --- a/administrator/components/com_admin/script.php +++ b/administrator/components/com_admin/script.php @@ -1407,6 +1407,7 @@ public function deleteUnexistingFiles() '/libraries/joomla/document/opensearch/opensearch.php', '/libraries/joomla/document/raw/raw.php', '/libraries/joomla/document/xml/xml.php', + '/administrator/components/com_installer/views/languages/tmpl/default_filter.php', ); // TODO There is an issue while deleting folders using the ftp mode diff --git a/administrator/components/com_installer/models/forms/filter_languages.xml b/administrator/components/com_installer/models/forms/filter_languages.xml new file mode 100644 index 0000000000000..63f91444fc926 --- /dev/null +++ b/administrator/components/com_installer/models/forms/filter_languages.xml @@ -0,0 +1,39 @@ + +
+ + + + + + + + + + + + + + + +
diff --git a/administrator/components/com_installer/models/languages.php b/administrator/components/com_installer/models/languages.php index b0b4294f637bd..d8a63821d01a4 100644 --- a/administrator/components/com_installer/models/languages.php +++ b/administrator/components/com_installer/models/languages.php @@ -41,8 +41,9 @@ public function __construct($config = array()) if (empty($config['filter_fields'])) { $config['filter_fields'] = array( - 'update_id', 'update_id', - 'name', 'name', + 'update_id', + 'name', + 'element', ); } @@ -99,7 +100,7 @@ protected function _getListQuery() $query = $db->getQuery(true); // Select the required fields from the updates table. - $query->select($db->quoteName(array('update_id', 'name', 'version', 'detailsurl', 'type'))) + $query->select($db->quoteName(array('update_id', 'name', 'element', 'version', 'detailsurl', 'type'))) ->from($db->quoteName('#__updates')); /* @@ -122,7 +123,6 @@ protected function _getListQuery() // Filter by search in title $search = $this->getState('filter.search'); - if (!empty($search)) { $search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%')); @@ -130,9 +130,7 @@ protected function _getListQuery() } // Add the list ordering clause. - $listOrder = $this->state->get('list.ordering'); - $orderDirn = $this->state->get('list.direction'); - $query->order($db->escape($listOrder) . ' ' . $db->escape($orderDirn)); + $query->order($db->escape($this->getState('list.ordering', 'name')) . ' ' . $db->escape($this->getState('list.direction', 'ASC'))); return $query; } @@ -168,12 +166,9 @@ protected function getStoreId($id = '') */ protected function populateState($ordering = 'name', $direction = 'asc') { - $app = JFactory::getApplication(); - - $value = $app->getUserStateFromRequest($this->context . '.filter.search', 'filter_search'); - $this->setState('filter.search', $value); + $this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string')); - $this->setState('extension_message', $app->getUserState('com_installer.extension_message')); + $this->setState('extension_message', JFactory::getApplication()->getUserState('com_installer.extension_message')); parent::populateState($ordering, $direction); } diff --git a/administrator/components/com_installer/views/languages/tmpl/default.php b/administrator/components/com_installer/views/languages/tmpl/default.php index b1f445d96faef..6693d9cf16a36 100644 --- a/administrator/components/com_installer/views/languages/tmpl/default.php +++ b/administrator/components/com_installer/views/languages/tmpl/default.php @@ -16,11 +16,9 @@ $listOrder = $this->escape($this->state->get('list.ordering')); $listDirn = $this->escape($this->state->get('list.direction')); -$version = new JVersion; - ?>
-
+ sidebar)) : ?>
sidebar; ?> @@ -28,34 +26,34 @@
- - items) || $this->escape($this->state->get('filter.search'))) : ?> - loadTemplate('filter'); ?> - items)) : ?> + + $this, 'options' => array('filterButton' => false))); ?> +
+ items)) : ?>
- + - - - - - @@ -67,7 +65,14 @@ - items as $i => $language) : ?> + getShortVersion()); + foreach ($this->items as $i => $language) : + // Get language code and language image. + preg_match('#^pkg_([a-z]{2,3}-[A-Z]{2})$#', $language->element, $element); + $language->code = $element[1]; + ?> - - -
+ - + - + + - + + + - + +
update_id, false, 'cid'); ?> @@ -75,39 +80,32 @@ - version; ?> + + code; ?> - type)); ?> + + + version, 0, 3) != $version::RELEASE || substr($language->version, 0, 5) != $currentShortVersion) : ?> + version; ?> + + version; ?> + - detailsurl; ?> + detailsurl; ?> + update_id; ?>
- - -
- - + - -
diff --git a/administrator/components/com_installer/views/languages/tmpl/default_filter.php b/administrator/components/com_installer/views/languages/tmpl/default_filter.php deleted file mode 100644 index 7e3a989fd97eb..0000000000000 --- a/administrator/components/com_installer/views/languages/tmpl/default_filter.php +++ /dev/null @@ -1,27 +0,0 @@ - -
-
- - pagination->getLimitBox(); ?> -
- -
- - -
-
-
diff --git a/administrator/components/com_installer/views/languages/view.html.php b/administrator/components/com_installer/views/languages/view.html.php index 00d439925fed3..0ffb1b9e836c8 100644 --- a/administrator/components/com_installer/views/languages/view.html.php +++ b/administrator/components/com_installer/views/languages/view.html.php @@ -47,9 +47,11 @@ public function display($tpl = null) $this->model->findLanguages(); // Get data from the model. - $this->state = $this->get('State'); - $this->items = $this->get('Items'); - $this->pagination = $this->get('Pagination'); + $this->state = $this->get('State'); + $this->items = $this->get('Items'); + $this->pagination = $this->get('Pagination'); + $this->filterForm = $this->get('FilterForm'); + $this->activeFilters = $this->get('ActiveFilters'); // Check for errors. if (count($errors = $this->get('Errors'))) diff --git a/administrator/components/com_messages/models/fields/messagestates.php b/administrator/components/com_messages/models/fields/messagestates.php new file mode 100644 index 0000000000000..fb0601ea934d1 --- /dev/null +++ b/administrator/components/com_messages/models/fields/messagestates.php @@ -0,0 +1,43 @@ + +
+ + + + + + + + + + + + + + + + + + + + + +
diff --git a/administrator/components/com_messages/models/messages.php b/administrator/components/com_messages/models/messages.php index 56a22b7c4eb7a..87f433cbacbc8 100644 --- a/administrator/components/com_messages/models/messages.php +++ b/administrator/components/com_messages/models/messages.php @@ -58,17 +58,15 @@ public function __construct($config = array()) * * @since 1.6 */ - protected function populateState($ordering = null, $direction = null) + protected function populateState($ordering = 'a.date_time', $direction = 'desc') { // Load the filter state. - $search = $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search'); - $this->setState('filter.search', $search); + $this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string')); - $state = $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'string'); - $this->setState('filter.state', $state); + $this->setState('filter.state', $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state', '', 'cmd')); // List state information. - parent::populateState('a.date_time', 'desc'); + parent::populateState($ordering, $direction); } /** @@ -128,7 +126,7 @@ protected function getListQuery() { $query->where('a.state = ' . (int) $state); } - elseif ($state === '') + elseif ($state !== '*') { $query->where('(a.state IN (0, 1))'); } diff --git a/administrator/components/com_messages/views/messages/tmpl/default.php b/administrator/components/com_messages/views/messages/tmpl/default.php index bc6ed8ad0102f..18d364221941e 100644 --- a/administrator/components/com_messages/views/messages/tmpl/default.php +++ b/administrator/components/com_messages/views/messages/tmpl/default.php @@ -40,23 +40,9 @@
- -
- -
- - -
-
- -
-
-
+ + $this)); ?> +
items)) : ?>
@@ -65,26 +51,26 @@ - - - - - - @@ -107,7 +93,7 @@ - @@ -118,8 +104,6 @@
- -
diff --git a/administrator/components/com_messages/views/messages/view.html.php b/administrator/components/com_messages/views/messages/view.html.php index 9ff87f4dca158..21f11321af087 100644 --- a/administrator/components/com_messages/views/messages/view.html.php +++ b/administrator/components/com_messages/views/messages/view.html.php @@ -33,9 +33,11 @@ class MessagesViewMessages extends JViewLegacy */ public function display($tpl = null) { - $this->items = $this->get('Items'); - $this->pagination = $this->get('Pagination'); - $this->state = $this->get('State'); + $this->items = $this->get('Items'); + $this->pagination = $this->get('Pagination'); + $this->state = $this->get('State'); + $this->filterForm = $this->get('FilterForm'); + $this->activeFilters = $this->get('ActiveFilters'); // Check for errors. if (count($errors = $this->get('Errors'))) diff --git a/administrator/language/en-GB/en-GB.com_installer.ini b/administrator/language/en-GB/en-GB.com_installer.ini index 7c7e9b551b0f7..40a531b5c1522 100644 --- a/administrator/language/en-GB/en-GB.com_installer.ini +++ b/administrator/language/en-GB/en-GB.com_installer.ini @@ -42,6 +42,9 @@ COM_INSTALLER_HEADING_FOLDER_ASC="Folder ascending" COM_INSTALLER_HEADING_FOLDER_DESC="Folder descending" COM_INSTALLER_HEADING_ID="ID" COM_INSTALLER_HEADING_INSTALLTYPE="Install Type" +COM_INSTALLER_HEADING_LANGUAGE_TAG="Language Tag" +COM_INSTALLER_HEADING_LANGUAGE_TAG_ASC="Language Tag ascending" +COM_INSTALLER_HEADING_LANGUAGE_TAG_DESC="Language Tag descending" COM_INSTALLER_HEADING_LOCATION="Location" COM_INSTALLER_HEADING_LOCATION_ASC="Location ascending" COM_INSTALLER_HEADING_LOCATION_DESC="Location descending" diff --git a/administrator/language/en-GB/en-GB.com_messages.ini b/administrator/language/en-GB/en-GB.com_messages.ini index 256189ec90ad6..394e0b5b8abef 100644 --- a/administrator/language/en-GB/en-GB.com_messages.ini +++ b/administrator/language/en-GB/en-GB.com_messages.ini @@ -27,9 +27,17 @@ COM_MESSAGES_FIELD_SUBJECT_LABEL="Subject" COM_MESSAGES_FIELD_USER_ID_FROM_LABEL="From" COM_MESSAGES_FIELD_USER_ID_TO_DESC="You must select a recipient." COM_MESSAGES_FIELD_USER_ID_TO_LABEL="Recipient" +COM_MESSAGES_FILTER_STATES_DESC="Filter by message state." +COM_MESSAGES_FILTER_STATES_LABEL="State" COM_MESSAGES_HEADING_FROM="From" +COM_MESSAGES_HEADING_FROM_ASC="From ascending" +COM_MESSAGES_HEADING_FROM_DESC="From descending" COM_MESSAGES_HEADING_READ="Read" +COM_MESSAGES_HEADING_READ_ASC="Read ascending" +COM_MESSAGES_HEADING_READ_DESC="Read descending" COM_MESSAGES_HEADING_SUBJECT="Subject" +COM_MESSAGES_HEADING_SUBJECT_ASC="Subject ascending" +COM_MESSAGES_HEADING_SUBJECT_DESC="Subject descending" COM_MESSAGES_INVALID_REPLY_ID="Invalid recipient" COM_MESSAGES_MANAGER_MESSAGES="Private Messages" COM_MESSAGES_MARK_AS_READ="Mark As Read" @@ -61,4 +69,4 @@ COM_MESSAGES_VIEW_PRIVATE_MESSAGE="Private Messages: View" COM_MESSAGES_WRITE_PRIVATE_MESSAGE="Private Messages: Write" COM_MESSAGES_XML_DESCRIPTION="Component for private messaging support in Backend." JLIB_APPLICATION_SAVE_SUCCESS="Message successfully sent." -JLIB_RULES_SETTING_NOTES="1. Changes apply to this component only.
Inherited - a Global Configuration setting or higher level setting is applied.
Denied always wins - whatever is set at the Global or higher level and applies to all child elements.
Allowed will enable the action for this component unless it is overruled by a Global Configuration setting.

2. Select Save to refresh the calculated settings." \ No newline at end of file +JLIB_RULES_SETTING_NOTES="1. Changes apply to this component only.
Inherited - a Global Configuration setting or higher level setting is applied.
Denied always wins - whatever is set at the Global or higher level and applies to all child elements.
Allowed will enable the action for this component unless it is overruled by a Global Configuration setting.

2. Select Save to refresh the calculated settings." diff --git a/layouts/joomla/sidebars/toggle.php b/layouts/joomla/sidebars/toggle.php index 4692618d7a06d..ff2bab50fac24 100644 --- a/layouts/joomla/sidebars/toggle.php +++ b/layouts/joomla/sidebars/toggle.php @@ -16,7 +16,6 @@
diff --git a/libraries/cms/application/cms.php b/libraries/cms/application/cms.php index ad46c24904b58..8e50ee6f282c2 100644 --- a/libraries/cms/application/cms.php +++ b/libraries/cms/application/cms.php @@ -227,7 +227,7 @@ public function checkSession() public function enqueueMessage($msg, $type = 'message') { // Don't add empty messages. - if (!strlen($msg)) + if (!strlen(trim($msg))) { return; } diff --git a/libraries/joomla/document/renderer/feed/atom.php b/libraries/joomla/document/renderer/feed/atom.php index 14cf3cb737c58..a4c925283dc59 100644 --- a/libraries/joomla/document/renderer/feed/atom.php +++ b/libraries/joomla/document/renderer/feed/atom.php @@ -120,7 +120,7 @@ public function render($name = '', $params = null, $content = null) $versionHtmlEscaped = ' version="' . htmlspecialchars(JVersion::RELEASE, ENT_COMPAT, 'UTF-8') . '"'; } - $feed .= " " . $data->getGenerator() . "\n"; + $feed .= " " . $data->getGenerator() . "\n"; $feed .= ' \n"; for ($i = 0, $count = count($data->items); $i < $count; $i++) diff --git a/libraries/joomla/filter/input.php b/libraries/joomla/filter/input.php index c3f09edb7768c..b1b8f38341962 100644 --- a/libraries/joomla/filter/input.php +++ b/libraries/joomla/filter/input.php @@ -9,6 +9,7 @@ defined('JPATH_PLATFORM') or die; +use Joomla\Filter\InputFilter; use Joomla\String\StringHelper; /** @@ -19,108 +20,16 @@ * * @since 11.1 */ -class JFilterInput +class JFilterInput extends InputFilter { - /** - * A container for JFilterInput instances. - * - * @var array - * @since 11.3 - */ - protected static $instances = array(); - - /** - * The array of permitted tags (white list). - * - * @var array - * @since 11.1 - */ - public $tagsArray; - - /** - * The array of permitted tag attributes (white list). - * - * @var array - * @since 11.1 - */ - public $attrArray; - - /** - * The method for sanitising tags: WhiteList method = 0 (default), BlackList method = 1 - * - * @var integer - * @since 11.1 - */ - public $tagsMethod; - - /** - * The method for sanitising attributes: WhiteList method = 0 (default), BlackList method = 1 - * - * @var integer - * @since 11.1 - */ - public $attrMethod; - - /** - * A flag for XSS checks. Only auto clean essentials = 0, Allow clean blacklisted tags/attr = 1 - * - * @var integer - * @since 11.1 - */ - public $xssAuto; - /** * A flag for Unicode Supplementary Characters (4-byte Unicode character) stripping. * * @var integer - * @since CMS 3.5.0 - */ - public $stripUSC = 0; - - /** - * The list of the default blacklisted tags. * - * @var array - * @since 11.1 - */ - public $tagBlacklist = array( - 'applet', - 'body', - 'bgsound', - 'base', - 'basefont', - 'embed', - 'frame', - 'frameset', - 'head', - 'html', - 'id', - 'iframe', - 'ilayer', - 'layer', - 'link', - 'meta', - 'name', - 'object', - 'script', - 'style', - 'title', - 'xml', - ); - - /** - * The list of the default blacklisted tag attributes. All event handlers implicit. - * - * @var array - * @since 11.1 + * @since 3.5 */ - public $attrBlacklist = array( - 'action', - 'background', - 'codebase', - 'dynsrc', - 'lowsrc', - ); + public $stripUSC = 0; /** * Constructor for inputFilter class. Only first parameter is required. @@ -147,7 +56,6 @@ public function __construct($tagsArray = array(), $attrArray = array(), $tagsMet $this->attrMethod = $attrMethod; $this->xssAuto = $xssAuto; $this->stripUSC = $stripUSC; - /** * If Unicode Supplementary Characters stripping is not set we have to check with the database driver. If the * driver does not support USCs (i.e. there is no utf8mb4 support) we will enable USC stripping. @@ -261,7 +169,6 @@ public function clean($source, $type = 'string') } break; - case 'UINT': $pattern = '/[-+]?[0-9]+/'; @@ -283,7 +190,6 @@ public function clean($source, $type = 'string') } break; - case 'FLOAT': case 'DOUBLE': $pattern = '/[-+]?[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?/'; @@ -306,9 +212,9 @@ public function clean($source, $type = 'string') } break; - case 'BOOL': case 'BOOLEAN': + if (is_array($source)) { $result = array(); @@ -325,7 +231,6 @@ public function clean($source, $type = 'string') } break; - case 'WORD': $pattern = '/[^A-Z_]/i'; @@ -345,7 +250,6 @@ public function clean($source, $type = 'string') } break; - case 'ALNUM': $pattern = '/[^A-Z0-9]/i'; @@ -365,7 +269,6 @@ public function clean($source, $type = 'string') } break; - case 'CMD': $pattern = '/[^A-Z0-9_\.-]/i'; @@ -387,7 +290,6 @@ public function clean($source, $type = 'string') } break; - case 'BASE64': $pattern = '/[^A-Z0-9\/+=]/i'; @@ -407,7 +309,6 @@ public function clean($source, $type = 'string') } break; - case 'STRING': if (is_array($source)) @@ -426,7 +327,6 @@ public function clean($source, $type = 'string') } break; - case 'HTML': if (is_array($source)) @@ -445,11 +345,10 @@ public function clean($source, $type = 'string') } break; - case 'ARRAY': $result = (array) $source; - break; + break; case 'PATH': $pattern = '/^[A-Za-z0-9_\/-]+[A-Za-z0-9_\.-]*([\\\\\/][A-Za-z0-9_-]+[A-Za-z0-9_\.-]*)*$/'; @@ -471,7 +370,6 @@ public function clean($source, $type = 'string') } break; - case 'TRIM': if (is_array($source)) @@ -494,7 +392,6 @@ public function clean($source, $type = 'string') } break; - case 'USERNAME': $pattern = '/[\x00-\x1F\x7F<>"\'%&]/'; @@ -514,12 +411,12 @@ public function clean($source, $type = 'string') } break; - case 'RAW': $result = $source; - break; + break; default: + // Are we dealing with an array? if (is_array($source)) { @@ -531,7 +428,6 @@ public function clean($source, $type = 'string') $source[$key] = $this->_remove($this->_decode($value)); } } - $result = $source; } else @@ -548,6 +444,7 @@ public function clean($source, $type = 'string') $result = $source; } } + break; } @@ -579,28 +476,6 @@ public function emailToPunycode($text) return $text; } - /** - * Function to determine if contents of an attribute are safe - * - * @param array $attrSubSet A 2 element array for attribute's name, value - * - * @return boolean True if bad code is detected - * - * @since 11.1 - */ - public static function checkAttribute($attrSubSet) - { - $attrSubSet[0] = strtolower($attrSubSet[0]); - $attrSubSet[1] = strtolower($attrSubSet[1]); - - return (((strpos($attrSubSet[1], 'expression') !== false) && ($attrSubSet[0]) == 'style') - || (strpos($attrSubSet[1], 'javascript:') !== false) - || (strpos($attrSubSet[1], 'behaviour:') !== false) - || (strpos($attrSubSet[1], 'vbscript:') !== false) - || (strpos($attrSubSet[1], 'mocha:') !== false) - || (strpos($attrSubSet[1], 'livescript:') !== false)); - } - /** * Checks an uploaded for suspicious naming and potential PHP contents which could indicate a hacking attempt. * @@ -626,22 +501,29 @@ public static function checkAttribute($attrSubSet) public static function isSafeFile($file, $options = array()) { $defaultOptions = array( + // Null byte in file name 'null_byte' => true, + // Forbidden string in extension (e.g. php matched .php, .xxx.php, .php.xxx and so on) 'forbidden_extensions' => array( 'php', 'phps', 'php5', 'php3', 'php4', 'inc', 'pl', 'cgi', 'fcgi', 'java', 'jar', 'py' ), + // true, + // true, + // Which file extensions to scan for short tags 'shorttag_extensions' => array( 'inc', 'phps', 'class', 'php3', 'php4', 'php5', 'txt', 'dat', 'tpl', 'tmpl' ), + // Forbidden extensions anywhere in the content 'fobidden_ext_in_content' => true, + // Which file extensions to scan for .php in the content 'php_ext_content_extensions' => array('zip', 'rar', 'tar', 'gz', 'tgz', 'bz2', 'tbz', 'jpa'), ); @@ -882,8 +764,8 @@ protected static function decodeFileData(array $data) * * @return string 'Cleaned' version of input parameter * - * @since 11.1 - * @deprecated 4.0 Use JFilterInput::remove() instead + * @since 11.1 + * @deprecated 4.0 Use JFilterInput::remove() instead */ protected function _remove($source) { @@ -919,8 +801,8 @@ protected function remove($source) * * @return string 'Cleaned' version of input parameter * - * @since 11.1 - * @deprecated 4.0 Use JFilterInput::cleanTags() instead + * @since 11.1 + * @deprecated 4.0 Use JFilterInput::cleanTags() instead */ protected function _cleanTags($source) { @@ -1039,7 +921,6 @@ protected function cleanTags($source) $nextSpace = strpos($fromSpace, ' '); $openQuotes = strpos($fromSpace, '"'); $closeQuotes = strpos(substr($fromSpace, ($openQuotes + 1)), '"') + $openQuotes + 1; - $startAtt = ''; $startAttPosition = 0; @@ -1065,6 +946,7 @@ protected function cleanTags($source) { $attribEnd = $nextSpace - 1; } + // If there is an ending, use this, if not, do not worry. if ($attribEnd > 0) { @@ -1074,8 +956,10 @@ protected function cleanTags($source) if (strpos($fromSpace, '=') !== false) { - // If the attribute value is wrapped in quotes we need to grab the substring from - // the closing quote, otherwise grab until the next space. + /* + * If the attribute value is wrapped in quotes we need to grab the substring from + * the closing quote, otherwise grab until the next space. + */ if (($openQuotes !== false) && (strpos(substr($fromSpace, ($openQuotes + 1)), '"') !== false)) { $attr = substr($fromSpace, 0, ($closeQuotes + 1)); @@ -1085,6 +969,7 @@ protected function cleanTags($source) $attr = substr($fromSpace, 0, $nextSpace); } } + // No more equal signs so add any extra text in the tag into the attribute array [eg. checked] else { @@ -1120,7 +1005,6 @@ protected function cleanTags($source) // Open or single tag $attrSet = $this->_cleanAttributes($attrSet); $preTag .= '<' . $tagName; - for ($i = 0, $count = count($attrSet); $i < $count; $i++) { $preTag .= ' ' . $attrSet[$i]; @@ -1136,6 +1020,7 @@ protected function cleanTags($source) $preTag .= ' />'; } } + // Closing tag else { @@ -1164,8 +1049,8 @@ protected function cleanTags($source) * * @return array Filtered array of attribute pairs * - * @since 11.1 - * @deprecated 4.0 Use JFilterInput::cleanAttributes() instead + * @since 11.1 + * @deprecated 4.0 Use JFilterInput::cleanAttributes() instead */ protected function _cleanAttributes($attrSet) { @@ -1173,106 +1058,62 @@ protected function _cleanAttributes($attrSet) } /** - * Internal method to strip a tag of certain attributes + * Escape < > and " inside attribute values * - * @param array $attrSet Array of attribute pairs to filter + * @param string $source The source string. * - * @return array Filtered array of attribute pairs + * @return string Filtered string * - * @since 3.5 + * @since 3.5 */ - protected function cleanAttributes($attrSet) + protected function escapeAttributeValues($source) { - $newSet = array(); - - $count = count($attrSet); + $alreadyFiltered = ''; + $remainder = $source; + $badChars = array('<', '"', '>'); + $escapedChars = array('<', '"', '>'); - // Iterate through attribute pairs - for ($i = 0; $i < $count; $i++) + /* + * Process each portion based on presence of =" and ", "/>, or "> + * See if there are any more attributes to process + */ + while (preg_match('#<[^>]*?=\s*?(\"|\')#s', $remainder, $matches, PREG_OFFSET_CAPTURE)) { - // Skip blank spaces - if (!$attrSet[$i]) - { - continue; - } - - // Split into name/value pairs - $attrSubSet = explode('=', trim($attrSet[$i]), 2); - - // Take the last attribute in case there is an attribute with no value - $attrSubSet_0 = explode(' ', trim($attrSubSet[0])); - $attrSubSet[0] = array_pop($attrSubSet_0); - - // Remove all "non-regular" attribute names - // AND blacklisted attributes + // Get the portion before the attribute value + $quotePosition = $matches[0][1]; + $nextBefore = $quotePosition + strlen($matches[0][0]); - if ((!preg_match('/[a-z]*$/i', $attrSubSet[0])) - || (($this->xssAuto) && ((in_array(strtolower($attrSubSet[0]), $this->attrBlacklist)) - || (substr($attrSubSet[0], 0, 2) == 'on')))) - { - continue; - } + /* + * Figure out if we have a single or double quote and look for the matching closing quote + * Closing quote should be "/>, ">, ", or " at the end of the string + */ + $quote = substr($matches[0][0], -1); + $pregMatch = ($quote == '"') ? '#(\"\s*/\s*>|\"\s*>|\"\s+|\"$)#' : "#(\'\s*/\s*>|\'\s*>|\'\s+|\'$)#"; - // XSS attribute value filtering - if (isset($attrSubSet[1])) + // Get the portion after attribute value + if (preg_match($pregMatch, substr($remainder, $nextBefore), $matches, PREG_OFFSET_CAPTURE)) { - // Trim leading and trailing spaces - $attrSubSet[1] = trim($attrSubSet[1]); - - // Strips unicode, hex, etc - $attrSubSet[1] = str_replace('&#', '', $attrSubSet[1]); - - // Strip normal newline within attr value - $attrSubSet[1] = preg_replace('/[\n\r]/', '', $attrSubSet[1]); - - // Strip double quotes - $attrSubSet[1] = str_replace('"', '', $attrSubSet[1]); - - // Convert single quotes from either side to doubles (Single quotes shouldn't be used to pad attr values) - if ((substr($attrSubSet[1], 0, 1) == "'") && (substr($attrSubSet[1], (strlen($attrSubSet[1]) - 1), 1) == "'")) - { - $attrSubSet[1] = substr($attrSubSet[1], 1, (strlen($attrSubSet[1]) - 2)); - } - // Strip slashes - $attrSubSet[1] = stripslashes($attrSubSet[1]); + // We have a closing quote + $nextAfter = $nextBefore + $matches[0][1]; } else { - continue; - } - - // Autostrip script tags - if (self::checkAttribute($attrSubSet)) - { - continue; + // No closing quote + $nextAfter = strlen($remainder); } - // Is our attribute in the user input array? - $attrFound = in_array(strtolower($attrSubSet[0]), $this->attrArray); + // Get the actual attribute value + $attributeValue = substr($remainder, $nextBefore, $nextAfter - $nextBefore); - // If the tag is allowed lets keep it - if ((!$attrFound && $this->attrMethod) || ($attrFound && !$this->attrMethod)) - { - // Does the attribute have a value? - if (empty($attrSubSet[1]) === false) - { - $newSet[] = $attrSubSet[0] . '="' . $attrSubSet[1] . '"'; - } - elseif ($attrSubSet[1] === "0") - { - // Special Case - // Is the value 0? - $newSet[] = $attrSubSet[0] . '="0"'; - } - else - { - // Leave empty attributes alone - $newSet[] = $attrSubSet[0] . '=""'; - } - } + // Escape bad chars + $attributeValue = str_replace($badChars, $escapedChars, $attributeValue); + $attributeValue = $this->_stripCSSExpressions($attributeValue); + $alreadyFiltered .= substr($remainder, 0, $nextBefore) . $attributeValue . $quote; + $remainder = substr($remainder, $nextAfter + 1); } - return $newSet; + // At this point, we just have to return the $alreadyFiltered and the $remainder + return $alreadyFiltered . $remainder; } /** @@ -1282,8 +1123,8 @@ protected function cleanAttributes($attrSet) * * @return string Plaintext string * - * @since 11.1 - * @deprecated 4.0 Use JFilterInput::decode() instead + * @since 11.1 + * @deprecated 4.0 Use JFilterInput::decode() instead */ protected function _decode($source) { @@ -1340,69 +1181,14 @@ protected function decode($source) * * @return string Filtered string * - * @since 11.1 - * @deprecated 4.0 Use JFilterInput::escapeAttributeValues() instead + * @since 11.1 + * @deprecated 4.0 Use JFilterInput::escapeAttributeValues() instead */ protected function _escapeAttributeValues($source) { return $this->escapeAttributeValues($source); } - /** - * Escape < > and " inside attribute values - * - * @param string $source The source string. - * - * @return string Filtered string - * - * @since 3.5 - */ - protected function escapeAttributeValues($source) - { - $alreadyFiltered = ''; - $remainder = $source; - $badChars = array('<', '"', '>'); - $escapedChars = array('<', '"', '>'); - - // Process each portion based on presence of =" and ", "/>, or "> - // See if there are any more attributes to process - while (preg_match('#<[^>]*?=\s*?(\"|\')#s', $remainder, $matches, PREG_OFFSET_CAPTURE)) - { - // Get the portion before the attribute value - $quotePosition = $matches[0][1]; - $nextBefore = $quotePosition + strlen($matches[0][0]); - - // Figure out if we have a single or double quote and look for the matching closing quote - // Closing quote should be "/>, ">, ", or " at the end of the string - $quote = substr($matches[0][0], -1); - $pregMatch = ($quote == '"') ? '#(\"\s*/\s*>|\"\s*>|\"\s+|\"$)#' : "#(\'\s*/\s*>|\'\s*>|\'\s+|\'$)#"; - - // Get the portion after attribute value - if (preg_match($pregMatch, substr($remainder, $nextBefore), $matches, PREG_OFFSET_CAPTURE)) - { - // We have a closing quote - $nextAfter = $nextBefore + $matches[0][1]; - } - else - { - // No closing quote - $nextAfter = strlen($remainder); - } - - // Get the actual attribute value - $attributeValue = substr($remainder, $nextBefore, $nextAfter - $nextBefore); - - // Escape bad chars - $attributeValue = str_replace($badChars, $escapedChars, $attributeValue); - $attributeValue = $this->_stripCSSExpressions($attributeValue); - $alreadyFiltered .= substr($remainder, 0, $nextBefore) . $attributeValue . $quote; - $remainder = substr($remainder, $nextAfter + 1); - } - - // At this point, we just have to return the $alreadyFiltered and the $remainder - return $alreadyFiltered . $remainder; - } - /** * Remove CSS Expressions in the form of `:expression(...)` * @@ -1418,41 +1204,6 @@ protected function _stripCSSExpressions($source) return $this->stripCSSExpressions($source); } - /** - * Remove CSS Expressions in the form of :expression(...) - * - * @param string $source The source string. - * - * @return string Filtered string - * - * @since 3.5 - */ - protected function stripCSSExpressions($source) - { - // Strip any comments out (in the form of /*...*/) - $test = preg_replace('#\/\*.*\*\/#U', '', $source); - - // Test for :expression - if (!stripos($test, ':expression')) - { - // Not found, so we are done - $return = $source; - } - else - { - // At this point, we have stripped out the comments and have found :expression - // Test stripped string for :expression followed by a '(' - if (preg_match_all('#:expression\s*\(#', $test, $matches)) - { - // If found, remove :expression - $test = str_ireplace(':expression', '', $test); - $return = $test; - } - } - - return $return; - } - /** * Recursively strip Unicode Supplementary Characters from the source. Not: objects cannot be filtered. * @@ -1460,7 +1211,7 @@ protected function stripCSSExpressions($source) * * @return mixed The filtered result * - * @since 3.5 + * @since 3.5 */ protected function stripUSC($source) { diff --git a/libraries/joomla/filter/output.php b/libraries/joomla/filter/output.php index 79e0b8be83cdc..4f19f2a2aada9 100644 --- a/libraries/joomla/filter/output.php +++ b/libraries/joomla/filter/output.php @@ -9,53 +9,15 @@ defined('JPATH_PLATFORM') or die; +use Joomla\Filter\OutputFilter; + /** * JFilterOutput * * @since 11.1 */ -class JFilterOutput +class JFilterOutput extends OutputFilter { - /** - * Makes an object safe to display in forms - * - * Object parameters that are non-string, array, object or start with underscore - * will be converted - * - * @param object &$mixed An object to be parsed - * @param integer $quote_style The optional quote style for the htmlspecialchars function - * @param mixed $exclude_keys An optional string single field name or array of field names not - * to be parsed (eg, for a textarea) - * - * @return void - * - * @since 11.1 - */ - public static function objectHTMLSafe(&$mixed, $quote_style = ENT_QUOTES, $exclude_keys = '') - { - if (is_object($mixed)) - { - foreach (get_object_vars($mixed) as $k => $v) - { - if (is_array($v) || is_object($v) || $v == null || substr($k, 1, 1) == '_') - { - continue; - } - - if (is_string($exclude_keys) && $k == $exclude_keys) - { - continue; - } - elseif (is_array($exclude_keys) && in_array($k, $exclude_keys)) - { - continue; - } - - $mixed->$k = htmlspecialchars($v, $quote_style, 'UTF-8'); - } - } - } - /** * This method processes a string and replaces all instances of & with & in links only. * @@ -102,7 +64,6 @@ public static function stringURLSafe($string) { // Remove any '-' from the string since they will be used as concatenaters $str = str_replace('-', ' ', $string); - $lang = JFactory::getLanguage(); $str = $lang->transliterate($str); @@ -118,63 +79,6 @@ public static function stringURLSafe($string) return $str; } - /** - * This method implements unicode slugs instead of transliteration. - * - * @param string $string String to process - * - * @return string Processed string - * - * @since 11.1 - */ - public static function stringURLUnicodeSlug($string) - { - // Replace double byte whitespaces by single byte (East Asian languages) - $str = preg_replace('/\xE3\x80\x80/', ' ', $string); - - // Remove any '-' from the string as they will be used as concatenator. - // Would be great to let the spaces in but only Firefox is friendly with this - - $str = str_replace('-', ' ', $str); - - // Replace forbidden characters by whitespaces - $str = preg_replace('#[:\#\*"@+=;!><&\.%()\]\/\'\\\\|\[]#', "\x20", $str); - - // Delete all '?' - $str = str_replace('?', '', $str); - - // Trim white spaces at beginning and end of alias and make lowercase - $str = trim(JString::strtolower($str)); - - // Remove any duplicate whitespace and replace whitespaces by hyphens - $str = preg_replace('#\x20+#', '-', $str); - - return $str; - } - - /** - * Replaces & with & for XHTML compliance - * - * @param string $text Text to process - * - * @return string Processed string. - * - * @since 11.1 - * - * @todo There must be a better way??? - */ - public static function ampReplace($text) - { - $text = str_replace('&&', '*--*', $text); - $text = str_replace('&#', '*-*', $text); - $text = str_replace('&', '&', $text); - $text = preg_replace('|&(?![\w]+;)|', '&', $text); - $text = str_replace('*-*', '&#', $text); - $text = str_replace('*--*', '&&', $text); - - return $text; - } - /** * Callback method for replacing & with & in a string * @@ -205,56 +109,4 @@ public static function _ampReplaceCallback($m) { return static::ampReplaceCallback($m); } - - /** - * Cleans text of all formatting and scripting code - * - * @param string &$text Text to clean - * - * @return string Cleaned text. - * - * @since 11.1 - */ - public static function cleanText(&$text) - { - $text = preg_replace("']*>.*?'si", '', $text); - $text = preg_replace('/]*>([^<]+)<\/a>/is', '\2 (\1)', $text); - $text = preg_replace('//', '', $text); - $text = preg_replace('/{.+?}/', '', $text); - $text = preg_replace('/ /', ' ', $text); - $text = preg_replace('/&/', ' ', $text); - $text = preg_replace('/"/', ' ', $text); - $text = strip_tags($text); - $text = htmlspecialchars($text, ENT_COMPAT, 'UTF-8'); - - return $text; - } - - /** - * Strip img-tags from string - * - * @param string $string Sting to be cleaned. - * - * @return string Cleaned string - * - * @since 11.1 - */ - public static function stripImages($string) - { - return preg_replace('#(<[/]?img.*>)#U', '', $string); - } - - /** - * Strip iframe-tags from string - * - * @param string $string Sting to be cleaned. - * - * @return string Cleaned string - * - * @since 12.2 - */ - public static function stripIframes($string) - { - return preg_replace('#(<[/]?iframe.*>)#U', '', $string); - } } diff --git a/modules/mod_tags_popular/helper.php b/modules/mod_tags_popular/helper.php index a0f334778d6d4..79a3faef8f7ba 100644 --- a/modules/mod_tags_popular/helper.php +++ b/modules/mod_tags_popular/helper.php @@ -73,6 +73,16 @@ public static function getList(&$params) $query->join('INNER', $db->quoteName('#__tags', 't') . ' ON ' . $db->quoteName('tag_id') . ' = t.id') ->join('INNER', $db->qn('#__ucm_content', 'c') . ' ON ' . $db->qn('m.core_content_id') . ' = ' . $db->qn('c.core_content_id')); + $query->where($db->quoteName('m.type_alias') . ' = ' . $db->quoteName('c.core_type_alias')); + + // Only return tags connected to published articles + $query->where($db->quoteName('c.core_state') . ' = 1') + ->where('(' . $db->quoteName('c.core_publish_up') . ' = ' . $nullDate + . ' OR ' . $db->quoteName('c.core_publish_up') . ' <= ' . $db->quote($nowDate) . ')') + ->where('(' . $db->quoteName('c.core_publish_down') . ' = ' . $nullDate + . ' OR ' . $db->quoteName('c.core_publish_down') . ' >= ' . $db->quote($nowDate) . ')'); + + // Set query depending on order_value param if ($order_value == 'rand()') { $query->order($query->Rand()); @@ -81,17 +91,32 @@ public static function getList(&$params) { $order_value = $db->quoteName($order_value); $order_direction = $params->get('order_direction', 1) ? 'DESC' : 'ASC'; - $query->order($order_value . ' ' . $order_direction); - } - $query->where($db->quoteName('m.type_alias') . ' = ' . $db->quoteName('c.core_type_alias')); + if ($params->get('order_value', 'title') == 'title') + { + $query->setLimit($maximum); + $query->order('count DESC'); + $equery = $db->getQuery(true) + ->select( + array( + 'a.tag_id', + 'a.count', + 'a.title', + 'a.access', + 'a.alias', + ) + ) + ->from('(' . (string) $query . ') AS a') + ->order('a.title' . ' ' . $order_direction); + + $query = $equery; + } + else + { + $query->order($order_value . ' ' . $order_direction); + } + } - // Only return tags connected to published articles - $query->where($db->quoteName('c.core_state') . ' = 1') - ->where('(' . $db->quoteName('c.core_publish_up') . ' = ' . $nullDate - . ' OR ' . $db->quoteName('c.core_publish_up') . ' <= ' . $db->quote($nowDate) . ')') - ->where('(' . $db->quoteName('c.core_publish_down') . ' = ' . $nullDate - . ' OR ' . $db->quoteName('c.core_publish_down') . ' >= ' . $db->quote($nowDate) . ')'); $db->setQuery($query, 0, $maximum); try
+ - + + - + + - + + - + +
+ pagination->getListFooter(); ?>
user_from; ?> + date_time, JText::_('DATE_FORMAT_LC2')); ?>