Spade

Mini Shell

Directory:~$ /home/lmsyaran/public_html/joomla4/
Upload File

[Home] [System Details] [Kill Me]
Current File:~$ /home/lmsyaran/public_html/joomla4/Document.tar

Document.php000064400000063776151157370770007073 0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Date\Date;

/**
 * Document class, provides an easy interface to parse and display a
document
 *
 * @since  1.7.0
 */
class Document
{
	/**
	 * Document title
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $title = '';

	/**
	 * Document description
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $description = '';

	/**
	 * Document full URL
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $link = '';

	/**
	 * Document base URL
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $base = '';

	/**
	 * Contains the document language setting
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $language = 'en-gb';

	/**
	 * Contains the document direction setting
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $direction = 'ltr';

	/**
	 * Document generator
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $_generator = 'Joomla! - Open Source Content Management';

	/**
	 * Document modified date
	 *
	 * @var    string|Date
	 * @since  1.7.0
	 */
	public $_mdate = '';

	/**
	 * Tab string
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $_tab = "\11";

	/**
	 * Contains the line end string
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $_lineEnd = "\12";

	/**
	 * Contains the character encoding string
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $_charset = 'utf-8';

	/**
	 * Document mime type
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $_mime = '';

	/**
	 * Document namespace
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $_namespace = '';

	/**
	 * Document profile
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $_profile = '';

	/**
	 * Array of linked scripts
	 *
	 * @var    array
	 * @since  1.7.0
	 */
	public $_scripts = array();

	/**
	 * Array of scripts placed in the header
	 *
	 * @var    array
	 * @since  1.7.0
	 */
	public $_script = array();

	/**
	 * Array of scripts options
	 *
	 * @var    array
	 */
	protected $scriptOptions = array();

	/**
	 * Array of linked style sheets
	 *
	 * @var    array
	 * @since  1.7.0
	 */
	public $_styleSheets = array();

	/**
	 * Array of included style declarations
	 *
	 * @var    array
	 * @since  1.7.0
	 */
	public $_style = array();

	/**
	 * Array of meta tags
	 *
	 * @var    array
	 * @since  1.7.0
	 */
	public $_metaTags = array();

	/**
	 * The rendering engine
	 *
	 * @var    object
	 * @since  1.7.0
	 */
	public $_engine = null;

	/**
	 * The document type
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $_type = null;

	/**
	 * Array of buffered output
	 *
	 * @var    mixed (depends on the renderer)
	 * @since  1.7.0
	 */
	public static $_buffer = null;

	/**
	 * Document instances container.
	 *
	 * @var    array
	 * @since  1.7.3
	 */
	protected static $instances = array();

	/**
	 * Media version added to assets
	 *
	 * @var    string
	 * @since  3.2
	 */
	protected $mediaVersion = null;

	/**
	 * Class constructor.
	 *
	 * @param   array  $options  Associative array of options
	 *
	 * @since   1.7.0
	 */
	public function __construct($options = array())
	{
		if (array_key_exists('lineend', $options))
		{
			$this->setLineEnd($options['lineend']);
		}

		if (array_key_exists('charset', $options))
		{
			$this->setCharset($options['charset']);
		}

		if (array_key_exists('language', $options))
		{
			$this->setLanguage($options['language']);
		}

		if (array_key_exists('direction', $options))
		{
			$this->setDirection($options['direction']);
		}

		if (array_key_exists('tab', $options))
		{
			$this->setTab($options['tab']);
		}

		if (array_key_exists('link', $options))
		{
			$this->setLink($options['link']);
		}

		if (array_key_exists('base', $options))
		{
			$this->setBase($options['base']);
		}

		if (array_key_exists('mediaversion', $options))
		{
			$this->setMediaVersion($options['mediaversion']);
		}
	}

	/**
	 * Returns the global Document object, only creating it
	 * if it doesn't already exist.
	 *
	 * @param   string  $type        The document type to instantiate
	 * @param   array   $attributes  Array of attributes
	 *
	 * @return  object  The document object.
	 *
	 * @since   1.7.0
	 */
	public static function getInstance($type = 'html', $attributes =
array())
	{
		$signature = serialize(array($type, $attributes));

		if (empty(self::$instances[$signature]))
		{
			$type  = preg_replace('/[^A-Z0-9_\.-]/i', '',
$type);
			$ntype = null;

			// Determine the path and class
			$class = __NAMESPACE__ . '\\' . ucfirst($type) .
'Document';

			if (!class_exists($class))
			{
				$class = 'JDocument' . ucfirst($type);
			}

			if (!class_exists($class))
			{
				// @deprecated 4.0 - Document objects should be autoloaded instead
				$path = __DIR__ . '/' . $type . '/' . $type .
'.php';

				\JLoader::register($class, $path);

				if (class_exists($class))
				{
					\JLog::add('Non-autoloadable Document subclasses are deprecated,
support will be removed in 4.0.', \JLog::WARNING,
'deprecated');
				}
				// Default to the raw format
				else
				{
					$ntype = $type;
					$class = 'JDocumentRaw';
				}
			}

			$instance = new $class($attributes);
			self::$instances[$signature] = $instance;

			if (!is_null($ntype))
			{
				// Set the type to the Document type originally requested
				$instance->setType($ntype);
			}
		}

		return self::$instances[$signature];
	}

	/**
	 * Set the document type
	 *
	 * @param   string  $type  Type document is to set to
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function setType($type)
	{
		$this->_type = $type;

		return $this;
	}

	/**
	 * Returns the document type
	 *
	 * @return  string
	 *
	 * @since   1.7.0
	 */
	public function getType()
	{
		return $this->_type;
	}

	/**
	 * Get the contents of the document buffer
	 *
	 * @return  mixed
	 *
	 * @since   1.7.0
	 */
	public function getBuffer()
	{
		return self::$_buffer;
	}

	/**
	 * Set the contents of the document buffer
	 *
	 * @param   string  $content  The content to be set in the buffer.
	 * @param   array   $options  Array of optional elements.
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function setBuffer($content, $options = array())
	{
		self::$_buffer = $content;

		return $this;
	}

	/**
	 * Gets a meta tag.
	 *
	 * @param   string  $name       Name of the meta HTML tag
	 * @param   string  $attribute  Attribute to use in the meta HTML tag
	 *
	 * @return  string
	 *
	 * @since   1.7.0
	 */
	public function getMetaData($name, $attribute = 'name')
	{
		// B/C old http_equiv parameter.
		if (!is_string($attribute))
		{
			$attribute = $attribute == true ? 'http-equiv' :
'name';
		}

		if ($name == 'generator')
		{
			$result = $this->getGenerator();
		}
		elseif ($name == 'description')
		{
			$result = $this->getDescription();
		}
		else
		{
			$result = isset($this->_metaTags[$attribute]) &&
isset($this->_metaTags[$attribute][$name]) ?
$this->_metaTags[$attribute][$name] : '';
		}

		return $result;
	}

	/**
	 * Sets or alters a meta tag.
	 *
	 * @param   string  $name       Name of the meta HTML tag
	 * @param   mixed   $content    Value of the meta HTML tag as array or
string
	 * @param   string  $attribute  Attribute to use in the meta HTML tag
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function setMetaData($name, $content, $attribute =
'name')
	{
		// Pop the element off the end of array if target function expects a
string or this http_equiv parameter.
		if (is_array($content) && (in_array($name,
array('generator', 'description')) ||
!is_string($attribute)))
		{
			$content = array_pop($content);
		}

		// B/C old http_equiv parameter.
		if (!is_string($attribute))
		{
			$attribute = $attribute == true ? 'http-equiv' :
'name';
		}

		if ($name == 'generator')
		{
			$this->setGenerator($content);
		}
		elseif ($name == 'description')
		{
			$this->setDescription($content);
		}
		else
		{
			$this->_metaTags[$attribute][$name] = $content;
		}

		return $this;
	}

	/**
	 * Adds a linked script to the page
	 *
	 * @param   string  $url      URL to the linked script.
	 * @param   array   $options  Array of options. Example:
array('version' => 'auto', 'conditional'
=> 'lt IE 9')
	 * @param   array   $attribs  Array of attributes. Example:
array('id' => 'scriptid', 'async' =>
'async', 'data-test' => 1)
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 * @deprecated 4.0  The (url, mime, defer, async) method signature is
deprecated, use (url, options, attributes) instead.
	 */
	public function addScript($url, $options = array(), $attribs = array())
	{
		// B/C before 3.7.0
		if (!is_array($options) && (!is_array($attribs) || $attribs ===
array()))
		{
			\JLog::add('The addScript method signature used has changed, use
(url, options, attributes) instead.', \JLog::WARNING,
'deprecated');

			$argList = func_get_args();
			$options = array();
			$attribs = array();

			// Old mime type parameter.
			if (!empty($argList[1]))
			{
				$attribs['mime'] = $argList[1];
			}

			// Old defer parameter.
			if (isset($argList[2]) && $argList[2])
			{
				$attribs['defer'] = true;
			}

			// Old async parameter.
			if (isset($argList[3]) && $argList[3])
			{
				$attribs['async'] = true;
			}
		}

		// Default value for type.
		if (!isset($attribs['type']) &&
!isset($attribs['mime']))
		{
			$attribs['type'] = 'text/javascript';
		}

		$this->_scripts[$url]            = isset($this->_scripts[$url]) ?
array_replace($this->_scripts[$url], $attribs) : $attribs;
		$this->_scripts[$url]['options'] =
isset($this->_scripts[$url]['options']) ?
array_replace($this->_scripts[$url]['options'], $options) :
$options;

		return $this;
	}

	/**
	 * Adds a linked script to the page with a version to allow to flush it.
Ex: myscript.js?54771616b5bceae9df03c6173babf11d
	 * If not specified Joomla! automatically handles versioning
	 *
	 * @param   string  $url      URL to the linked script.
	 * @param   array   $options  Array of options. Example:
array('version' => 'auto', 'conditional'
=> 'lt IE 9')
	 * @param   array   $attribs  Array of attributes. Example:
array('id' => 'scriptid', 'async' =>
'async', 'data-test' => 1)
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   3.2
	 * @deprecated 4.0  This method is deprecated, use addScript(url, options,
attributes) instead.
	 */
	public function addScriptVersion($url, $options = array(), $attribs =
array())
	{
		\JLog::add('The method is deprecated, use addScript(url, attributes,
options) instead.', \JLog::WARNING, 'deprecated');

		// B/C before 3.7.0
		if (!is_array($options) && (!is_array($attribs) || $attribs ===
array()))
		{
			$argList = func_get_args();
			$options = array();
			$attribs = array();

			// Old version parameter.
			$options['version'] = isset($argList[1]) &&
!is_null($argList[1]) ? $argList[1] : 'auto';

			// Old mime type parameter.
			if (!empty($argList[2]))
			{
				$attribs['mime'] = $argList[2];
			}

			// Old defer parameter.
			if (isset($argList[3]) && $argList[3])
			{
				$attribs['defer'] = true;
			}

			// Old async parameter.
			if (isset($argList[4]) && $argList[4])
			{
				$attribs['async'] = true;
			}
		}
		// Default value for version.
		else
		{
			$options['version'] = 'auto';
		}

		return $this->addScript($url, $options, $attribs);
	}

	/**
	 * Adds a script to the page
	 *
	 * @param   string  $content  Script
	 * @param   string  $type     Scripting mime (defaults to
'text/javascript')
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function addScriptDeclaration($content, $type =
'text/javascript')
	{
		if (!isset($this->_script[strtolower($type)]))
		{
			$this->_script[strtolower($type)] = $content;
		}
		else
		{
			$this->_script[strtolower($type)] .= chr(13) . $content;
		}

		return $this;
	}

	/**
	 * Add option for script
	 *
	 * @param   string  $key      Name in Storage
	 * @param   mixed   $options  Scrip options as array or string
	 * @param   bool    $merge    Whether merge with existing (true) or
replace (false)
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   3.5
	 */
	public function addScriptOptions($key, $options, $merge = true)
	{
		if (empty($this->scriptOptions[$key]))
		{
			$this->scriptOptions[$key] = array();
		}

		if ($merge && is_array($options))
		{
			$this->scriptOptions[$key] =
array_replace_recursive($this->scriptOptions[$key], $options);
		}
		else
		{
			$this->scriptOptions[$key] = $options;
		}

		return $this;
	}

	/**
	 * Get script(s) options
	 *
	 * @param   string  $key  Name in Storage
	 *
	 * @return  array  Options for given $key, or all script options
	 *
	 * @since   3.5
	 */
	public function getScriptOptions($key = null)
	{
		if ($key)
		{
			return (empty($this->scriptOptions[$key])) ? array() :
$this->scriptOptions[$key];
		}
		else
		{
			return $this->scriptOptions;
		}
	}

	/**
	 * Adds a linked stylesheet to the page
	 *
	 * @param   string  $url      URL to the linked style sheet
	 * @param   array   $options  Array of options. Example:
array('version' => 'auto', 'conditional'
=> 'lt IE 9')
	 * @param   array   $attribs  Array of attributes. Example:
array('id' => 'stylesheet', 'data-test'
=> 1)
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 * @deprecated 4.0  The (url, mime, media, attribs) method signature is
deprecated, use (url, options, attributes) instead.
	 */
	public function addStyleSheet($url, $options = array(), $attribs =
array())
	{
		// B/C before 3.7.0
		if (is_string($options))
		{
			\JLog::add('The addStyleSheet method signature used has changed,
use (url, options, attributes) instead.', \JLog::WARNING,
'deprecated');

			$argList = func_get_args();
			$options = array();
			$attribs = array();

			// Old mime type parameter.
			if (!empty($argList[1]))
			{
				$attribs['type'] = $argList[1];
			}

			// Old media parameter.
			if (isset($argList[2]) && $argList[2])
			{
				$attribs['media'] = $argList[2];
			}

			// Old attribs parameter.
			if (isset($argList[3]) && $argList[3])
			{
				$attribs = array_replace($attribs, $argList[3]);
			}
		}

		// Default value for type.
		if (!isset($attribs['type']) &&
!isset($attribs['mime']))
		{
			$attribs['type'] = 'text/css';
		}

		$this->_styleSheets[$url] = isset($this->_styleSheets[$url]) ?
array_replace($this->_styleSheets[$url], $attribs) : $attribs;

		if (isset($this->_styleSheets[$url]['options']))
		{
			$this->_styleSheets[$url]['options'] =
array_replace($this->_styleSheets[$url]['options'], $options);
		}
		else
		{
			$this->_styleSheets[$url]['options'] = $options;
		}

		return $this;
	}

	/**
	 * Adds a linked stylesheet version to the page. Ex:
template.css?54771616b5bceae9df03c6173babf11d
	 * If not specified Joomla! automatically handles versioning
	 *
	 * @param   string  $url      URL to the linked style sheet
	 * @param   array   $options  Array of options. Example:
array('version' => 'auto', 'conditional'
=> 'lt IE 9')
	 * @param   array   $attribs  Array of attributes. Example:
array('id' => 'stylesheet', 'data-test'
=> 1)
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   3.2
	 * @deprecated 4.0  This method is deprecated, use addStyleSheet(url,
options, attributes) instead.
	 */
	public function addStyleSheetVersion($url, $options = array(), $attribs =
array())
	{
		\JLog::add('The method is deprecated, use addStyleSheet(url,
attributes, options) instead.', \JLog::WARNING,
'deprecated');

		// B/C before 3.7.0
		if (!is_array($options) && (!is_array($attribs) || $attribs ===
array()))
		{
			$argList = func_get_args();
			$options = array();
			$attribs = array();

			// Old version parameter.
			$options['version'] = isset($argList[1]) &&
!is_null($argList[1]) ? $argList[1] : 'auto';

			// Old mime type parameter.
			if (!empty($argList[2]))
			{
				$attribs['mime'] = $argList[2];
			}

			// Old media parameter.
			if (isset($argList[3]) && $argList[3])
			{
				$attribs['media'] = $argList[3];
			}

			// Old attribs parameter.
			if (isset($argList[4]) && $argList[4])
			{
				$attribs = array_replace($attribs, $argList[4]);
			}
		}
		// Default value for version.
		else
		{
			$options['version'] = 'auto';
		}

		return $this->addStyleSheet($url, $options, $attribs);
	}

	/**
	 * Adds a stylesheet declaration to the page
	 *
	 * @param   string  $content  Style declarations
	 * @param   string  $type     Type of stylesheet (defaults to
'text/css')
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function addStyleDeclaration($content, $type =
'text/css')
	{
		if (!isset($this->_style[strtolower($type)]))
		{
			$this->_style[strtolower($type)] = $content;
		}
		else
		{
			$this->_style[strtolower($type)] .= chr(13) . $content;
		}

		return $this;
	}

	/**
	 * Sets the document charset
	 *
	 * @param   string  $type  Charset encoding string
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function setCharset($type = 'utf-8')
	{
		$this->_charset = $type;

		return $this;
	}

	/**
	 * Returns the document charset encoding.
	 *
	 * @return  string
	 *
	 * @since   1.7.0
	 */
	public function getCharset()
	{
		return $this->_charset;
	}

	/**
	 * Sets the global document language declaration. Default is English
(en-gb).
	 *
	 * @param   string  $lang  The language to be set
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function setLanguage($lang = 'en-gb')
	{
		$this->language = strtolower($lang);

		return $this;
	}

	/**
	 * Returns the document language.
	 *
	 * @return  string
	 *
	 * @since   1.7.0
	 */
	public function getLanguage()
	{
		return $this->language;
	}

	/**
	 * Sets the global document direction declaration. Default is
left-to-right (ltr).
	 *
	 * @param   string  $dir  The language direction to be set
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function setDirection($dir = 'ltr')
	{
		$this->direction = strtolower($dir);

		return $this;
	}

	/**
	 * Returns the document direction declaration.
	 *
	 * @return  string
	 *
	 * @since   1.7.0
	 */
	public function getDirection()
	{
		return $this->direction;
	}

	/**
	 * Sets the title of the document
	 *
	 * @param   string  $title  The title to be set
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function setTitle($title)
	{
		$this->title = $title;

		return $this;
	}

	/**
	 * Return the title of the document.
	 *
	 * @return  string
	 *
	 * @since   1.7.0
	 */
	public function getTitle()
	{
		return $this->title;
	}

	/**
	 * Set the assets version
	 *
	 * @param   string  $mediaVersion  Media version to use
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   3.2
	 */
	public function setMediaVersion($mediaVersion)
	{
		$this->mediaVersion = strtolower($mediaVersion);

		return $this;
	}

	/**
	 * Return the media version
	 *
	 * @return  string
	 *
	 * @since   3.2
	 */
	public function getMediaVersion()
	{
		return $this->mediaVersion;
	}

	/**
	 * Sets the base URI of the document
	 *
	 * @param   string  $base  The base URI to be set
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function setBase($base)
	{
		$this->base = $base;

		return $this;
	}

	/**
	 * Return the base URI of the document.
	 *
	 * @return  string
	 *
	 * @since   1.7.0
	 */
	public function getBase()
	{
		return $this->base;
	}

	/**
	 * Sets the description of the document
	 *
	 * @param   string  $description  The description to set
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function setDescription($description)
	{
		$this->description = $description;

		return $this;
	}

	/**
	 * Return the description of the document.
	 *
	 * @return  string
	 *
	 * @since    1.7.0
	 */
	public function getDescription()
	{
		return $this->description;
	}

	/**
	 * Sets the document link
	 *
	 * @param   string  $url  A url
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function setLink($url)
	{
		$this->link = $url;

		return $this;
	}

	/**
	 * Returns the document base url
	 *
	 * @return string
	 *
	 * @since   1.7.0
	 */
	public function getLink()
	{
		return $this->link;
	}

	/**
	 * Sets the document generator
	 *
	 * @param   string  $generator  The generator to be set
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function setGenerator($generator)
	{
		$this->_generator = $generator;

		return $this;
	}

	/**
	 * Returns the document generator
	 *
	 * @return  string
	 *
	 * @since   1.7.0
	 */
	public function getGenerator()
	{
		return $this->_generator;
	}

	/**
	 * Sets the document modified date
	 *
	 * @param   string|Date  $date  The date to be set
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 * @throws  \InvalidArgumentException
	 */
	public function setModifiedDate($date)
	{
		if (!is_string($date) && !($date instanceof Date))
		{
			throw new \InvalidArgumentException(
				sprintf(
					'The $date parameter of %1$s must be a string or a %2$s instance,
a %3$s was given.',
					__METHOD__ . '()',
					'Joomla\\CMS\\Date\\Date',
					gettype($date) === 'object' ? (get_class($date) . '
instance') : gettype($date)
				)
			);
		}

		$this->_mdate = $date;

		return $this;
	}

	/**
	 * Returns the document modified date
	 *
	 * @return  string|Date
	 *
	 * @since   1.7.0
	 */
	public function getModifiedDate()
	{
		return $this->_mdate;
	}

	/**
	 * Sets the document MIME encoding that is sent to the browser.
	 *
	 * This usually will be text/html because most browsers cannot yet
	 * accept the proper mime settings for XHTML: application/xhtml+xml
	 * and to a lesser extent application/xml and text/xml. See the W3C note
	 * ({@link http://www.w3.org/TR/xhtml-media-types/
	 * http://www.w3.org/TR/xhtml-media-types/}) for more details.
	 *
	 * @param   string   $type  The document type to be sent
	 * @param   boolean  $sync  Should the type be synced with HTML?
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 *
	 * @link    http://www.w3.org/TR/xhtml-media-types
	 */
	public function setMimeEncoding($type = 'text/html', $sync =
true)
	{
		$this->_mime = strtolower($type);

		// Syncing with metadata
		if ($sync)
		{
			$this->setMetaData('content-type', $type . ';
charset=' . $this->_charset, true);
		}

		return $this;
	}

	/**
	 * Return the document MIME encoding that is sent to the browser.
	 *
	 * @return  string
	 *
	 * @since   1.7.0
	 */
	public function getMimeEncoding()
	{
		return $this->_mime;
	}

	/**
	 * Sets the line end style to Windows, Mac, Unix or a custom string.
	 *
	 * @param   string  $style  "win", "mac",
"unix" or custom string.
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function setLineEnd($style)
	{
		switch ($style)
		{
			case 'win':
				$this->_lineEnd = "\15\12";
				break;
			case 'unix':
				$this->_lineEnd = "\12";
				break;
			case 'mac':
				$this->_lineEnd = "\15";
				break;
			default:
				$this->_lineEnd = $style;
		}

		return $this;
	}

	/**
	 * Returns the lineEnd
	 *
	 * @return  string
	 *
	 * @since   1.7.0
	 */
	public function _getLineEnd()
	{
		return $this->_lineEnd;
	}

	/**
	 * Sets the string used to indent HTML
	 *
	 * @param   string  $string  String used to indent ("\11",
"\t", '  ', etc.).
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function setTab($string)
	{
		$this->_tab = $string;

		return $this;
	}

	/**
	 * Returns a string containing the unit for indenting HTML
	 *
	 * @return  string
	 *
	 * @since   1.7.0
	 */
	public function _getTab()
	{
		return $this->_tab;
	}

	/**
	 * Load a renderer
	 *
	 * @param   string  $type  The renderer type
	 *
	 * @return  DocumentRenderer
	 *
	 * @since   1.7.0
	 * @throws  \RuntimeException
	 */
	public function loadRenderer($type)
	{
		// Determine the path and class
		$class = __NAMESPACE__ . '\\Renderer\\' .
ucfirst($this->getType()) . '\\' . ucfirst($type) .
'Renderer';

		if (!class_exists($class))
		{
			$class = 'JDocumentRenderer' . ucfirst($this->getType()) .
ucfirst($type);
		}

		if (!class_exists($class))
		{
			// "Legacy" class name structure
			$class = 'JDocumentRenderer' . $type;

			if (!class_exists($class))
			{
				// @deprecated 4.0 - Non-autoloadable class support is deprecated, only
log a message though if a file is found
				$path = __DIR__ . '/' . $this->getType() .
'/renderer/' . $type . '.php';

				if (!file_exists($path))
				{
					throw new \RuntimeException('Unable to load renderer class',
500);
				}

				\JLoader::register($class, $path);

				\JLog::add('Non-autoloadable JDocumentRenderer subclasses are
deprecated, support will be removed in 4.0.', \JLog::WARNING,
'deprecated');

				// If the class still doesn't exist after including the path,
we've got issues
				if (!class_exists($class))
				{
					throw new \RuntimeException('Unable to load renderer class',
500);
				}
			}
		}

		return new $class($this);
	}

	/**
	 * Parses the document and prepares the buffers
	 *
	 * @param   array  $params  The array of parameters
	 *
	 * @return  Document instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function parse($params = array())
	{
		return $this;
	}

	/**
	 * Outputs the document
	 *
	 * @param   boolean  $cache   If true, cache the output
	 * @param   array    $params  Associative array of attributes
	 *
	 * @return  void  The rendered data
	 *
	 * @since   1.7.0
	 */
	public function render($cache = false, $params = array())
	{
		$app = \JFactory::getApplication();

		if ($mdate = $this->getModifiedDate())
		{
			if (!($mdate instanceof Date))
			{
				$mdate = new Date($mdate);
			}

			$app->modifiedDate = $mdate;
		}

		$app->mimeType = $this->_mime;
		$app->charSet  = $this->_charset;
	}
}
DocumentRenderer.php000064400000003466151157370770010550 0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Uri\Uri;

/**
 * Abstract class for a renderer
 *
 * @since  1.7.0
 */
class DocumentRenderer
{
	/**
	 * Reference to the Document object that instantiated the renderer
	 *
	 * @var    Document
	 * @since  1.7.0
	 */
	protected $_doc = null;

	/**
	 * Renderer mime type
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	protected $_mime = 'text/html';

	/**
	 * Class constructor
	 *
	 * @param   Document  $doc  A reference to the Document object that
instantiated the renderer
	 *
	 * @since   1.7.0
	 */
	public function __construct(Document $doc)
	{
		$this->_doc = $doc;
	}

	/**
	 * Renders a script and returns the results as a string
	 *
	 * @param   string  $name     The name of the element to render
	 * @param   array   $params   Array of values
	 * @param   string  $content  Override the output of the renderer
	 *
	 * @return  string  The output of the script
	 *
	 * @since   1.7.0
	 */
	public function render($name, $params = null, $content = null)
	{
	}

	/**
	 * Return the content type of the renderer
	 *
	 * @return  string  The contentType
	 *
	 * @since   1.7.0
	 */
	public function getContentType()
	{
		return $this->_mime;
	}

	/**
	 * Convert links in a text from relative to absolute
	 *
	 * @param   string  $text  The text processed
	 *
	 * @return  string   Text with converted links
	 *
	 * @since   1.7.0
	 */
	protected function _relToAbs($text)
	{
		$base = Uri::base();
		$text =
preg_replace("/(href|src)=\"(?!http|ftp|https|mailto|data|\/\/)([^\"]*)\"/",
"$1=\"$base\$2\"", $text);

		return $text;
	}
}
ErrorDocument.php000064400000011311151157370770010057 0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Layout\LayoutHelper;
use Joomla\CMS\Uri\Uri;

/**
 * ErrorDocument class, provides an easy interface to parse and display an
error page
 *
 * @since  1.7.0
 */
class ErrorDocument extends Document
{
	/**
	 * Document base URL
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $baseurl = '';

	/**
	 * Flag if debug mode has been enabled
	 *
	 * @var    boolean
	 * @since  1.7.0
	 */
	public $debug = false;

	/**
	 * Error Object
	 *
	 * @var    \Exception|\Throwable
	 * @since  1.7.0
	 */
	public $error;

	/**
	 * Name of the template
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $template = null;

	/**
	 * File name
	 *
	 * @var    array
	 * @since  1.7.0
	 */
	public $_file = null;

	/**
	 * Error Object
	 *
	 * @var    \Exception|\Throwable
	 * @since  1.7.0
	 */
	protected $_error;

	/**
	 * Class constructor
	 *
	 * @param   array  $options  Associative array of attributes
	 *
	 * @since   1.7.0
	 */
	public function __construct($options = array())
	{
		parent::__construct($options);

		// Set mime type
		$this->_mime = 'text/html';

		// Set document type
		$this->_type = 'error';
	}

	/**
	 * Set error object
	 *
	 * @param   \Exception|\Throwable  $error  Error object to set
	 *
	 * @return  boolean  True on success
	 *
	 * @since   1.7.0
	 */
	public function setError($error)
	{
		$expectedClass = PHP_MAJOR_VERSION >= 7 ? '\\Throwable' :
'\\Exception';

		if ($error instanceof $expectedClass)
		{
			$this->_error = & $error;

			return true;
		}

		return false;
	}

	/**
	 * Render the document
	 *
	 * @param   boolean  $cache   If true, cache the output
	 * @param   array    $params  Associative array of attributes
	 *
	 * @return  string   The rendered data
	 *
	 * @since   1.7.0
	 */
	public function render($cache = false, $params = array())
	{
		// If no error object is set return null
		if (!isset($this->_error))
		{
			return;
		}

		// Set the status header
		$status = $this->_error->getCode();

		if ($status < 400 || $status > 599)
		{
			$status = 500;
		}

		$errorReporting =
\JFactory::getConfig()->get('error_reporting');

		if ($errorReporting === "development" || $errorReporting ===
"maximum")
		{
			$status .= ' ' . str_replace("\n", ' ',
$this->_error->getMessage());
		}

		\JFactory::getApplication()->setHeader('status', $status);

		$file = 'error.php';

		// Check template
		$directory = isset($params['directory']) ?
$params['directory'] : 'templates';
		$template = isset($params['template']) ?
\JFilterInput::getInstance()->clean($params['template'],
'cmd') : 'system';

		if (!file_exists($directory . '/' . $template . '/' .
$file))
		{
			$template = 'system';
		}

		// Set variables
		$this->baseurl = Uri::base(true);
		$this->template = $template;
		$this->debug = isset($params['debug']) ?
$params['debug'] : false;
		$this->error = $this->_error;

		// Load the language file for the template if able
		if (\JFactory::$language)
		{
			$lang = \JFactory::getLanguage();

			// 1.5 or core then 1.6
			$lang->load('tpl_' . $template, JPATH_BASE, null, false,
true)
				|| $lang->load('tpl_' . $template, $directory .
'/' . $template, null, false, true);
		}

		// Load
		$data = $this->_loadTemplate($directory . '/' . $template,
$file);

		parent::render($cache, $params);

		return $data;
	}

	/**
	 * Load a template file
	 *
	 * @param   string  $directory  The name of the template
	 * @param   string  $filename   The actual filename
	 *
	 * @return  string  The contents of the template
	 *
	 * @since   1.7.0
	 */
	public function _loadTemplate($directory, $filename)
	{
		$contents = '';

		// Check to see if we have a valid template file
		if (file_exists($directory . '/' . $filename))
		{
			// Store the file path
			$this->_file = $directory . '/' . $filename;

			// Get the file content
			ob_start();
			require_once $directory . '/' . $filename;
			$contents = ob_get_contents();
			ob_end_clean();
		}

		return $contents;
	}

	/**
	 * Render the backtrace
	 *
	 * @return  string  The contents of the backtrace
	 *
	 * @since   1.7.0
	 */
	public function renderBacktrace()
	{
		// If no error object is set return null
		if (!isset($this->_error))
		{
			return;
		}

		// The back trace
		$backtrace = $this->_error->getTrace();

		// Add the position of the actual file
		array_unshift($backtrace, array('file' =>
$this->_error->getFile(), 'line' =>
$this->_error->getLine(), 'function' => ''));

		return LayoutHelper::render('joomla.error.backtrace',
array('backtrace' => $backtrace));
	}
}
Feed/FeedEnclosure.php000064400000001343151157370770010661 0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document\Feed;

defined('JPATH_PLATFORM') or die;

/**
 * Data object representing a feed enclosure
 *
 * @since  1.7.0
 */
class FeedEnclosure
{
	/**
	 * URL enclosure element
	 *
	 * required
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $url = '';

	/**
	 * Length enclosure element
	 *
	 * required
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $length = '';

	/**
	 * Type enclosure element
	 *
	 * required
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $type = '';
}
Feed/FeedImage.php000064400000002045151157371000007727 0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document\Feed;

defined('JPATH_PLATFORM') or die;

/**
 * Data object representing a feed image
 *
 * @since  1.7.0
 */
class FeedImage
{
	/**
	 * Title image attribute
	 *
	 * required
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $title = '';

	/**
	 * URL image attribute
	 *
	 * required
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $url = '';

	/**
	 * Link image attribute
	 *
	 * required
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $link = '';

	/**
	 * Width image attribute
	 *
	 * optional
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $width;

	/**
	 * Title feed attribute
	 *
	 * optional
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $height;

	/**
	 * Title feed attribute
	 *
	 * optional
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $description;
}
Feed/FeedItem.php000064400000004114151157371000007602 0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document\Feed;

defined('JPATH_PLATFORM') or die;

/**
 * Data object representing a feed item
 *
 * @since  1.7.0
 */
class FeedItem
{
	/**
	 * Title item element
	 *
	 * required
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $title;

	/**
	 * Link item element
	 *
	 * required
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $link;

	/**
	 * Description item element
	 *
	 * required
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $description;

	/**
	 * Author item element
	 *
	 * optional
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $author;

	/**
	 * Author email element
	 *
	 * optional
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $authorEmail;

	/**
	 * Category element
	 *
	 * optional
	 *
	 * @var    array or string
	 * @since  1.7.0
	 */
	public $category;

	/**
	 * Comments element
	 *
	 * optional
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $comments;

	/**
	 * Enclosure element
	 *
	 * @var    FeedEnclosure
	 * @since  1.7.0
	 */
	public $enclosure = null;

	/**
	 * Guid element
	 *
	 * optional
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $guid;

	/**
	 * Published date
	 *
	 * optional
	 *
	 * May be in one of the following formats:
	 *
	 * RFC 822:
	 * "Mon, 20 Jan 03 18:05:41 +0400"
	 * "20 Jan 03 18:05:41 +0000"
	 *
	 * ISO 8601:
	 * "2003-01-20T18:05:41+04:00"
	 *
	 * Unix:
	 * 1043082341
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $date;

	/**
	 * Source element
	 *
	 * optional
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $source;

	/**
	 * Set the FeedEnclosure for this item
	 *
	 * @param   FeedEnclosure  $enclosure  The FeedEnclosure to add to the
feed.
	 *
	 * @return  FeedItem instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function setEnclosure(FeedEnclosure $enclosure)
	{
		$this->enclosure = $enclosure;

		return $this;
	}
}
FeedDocument.php000064400000007755151157371000007635 0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Document\Feed\FeedImage;
use Joomla\CMS\Document\Feed\FeedItem;

/**
 * FeedDocument class, provides an easy interface to parse and display any
feed document
 *
 * @since  1.7.0
 */
class FeedDocument extends Document
{
	/**
	 * Syndication URL feed element
	 *
	 * optional
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $syndicationURL = '';

	/**
	 * Image feed element
	 *
	 * optional
	 *
	 * @var    FeedImage
	 * @since  1.7.0
	 */
	public $image = null;

	/**
	 * Copyright feed element
	 *
	 * optional
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $copyright = '';

	/**
	 * Published date feed element
	 *
	 * optional
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $pubDate = '';

	/**
	 * Lastbuild date feed element
	 *
	 * optional
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $lastBuildDate = '';

	/**
	 * Editor feed element
	 *
	 * optional
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $editor = '';

	/**
	 * Docs feed element
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $docs = '';

	/**
	 * Editor email feed element
	 *
	 * optional
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $editorEmail = '';

	/**
	 * Webmaster email feed element
	 *
	 * optional
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $webmaster = '';

	/**
	 * Category feed element
	 *
	 * optional
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $category = '';

	/**
	 * TTL feed attribute
	 *
	 * optional
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $ttl = '';

	/**
	 * Rating feed element
	 *
	 * optional
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $rating = '';

	/**
	 * Skiphours feed element
	 *
	 * optional
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $skipHours = '';

	/**
	 * Skipdays feed element
	 *
	 * optional
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $skipDays = '';

	/**
	 * The feed items collection
	 *
	 * @var    FeedItem[]
	 * @since  1.7.0
	 */
	public $items = array();

	/**
	 * Class constructor
	 *
	 * @param   array  $options  Associative array of options
	 *
	 * @since  1.7.0
	 */
	public function __construct($options = array())
	{
		parent::__construct($options);

		// Set document type
		$this->_type = 'feed';
	}

	/**
	 * Render the document
	 *
	 * @param   boolean  $cache   If true, cache the output
	 * @param   array    $params  Associative array of attributes
	 *
	 * @return  string The rendered data
	 *
	 * @since   1.7.0
	 * @throws  \Exception
	 * @todo    Make this cacheable
	 */
	public function render($cache = false, $params = array())
	{
		// Get the feed type
		$type = \JFactory::getApplication()->input->get('type',
'rss');

		// Instantiate feed renderer and set the mime encoding
		$renderer = $this->loadRenderer(($type) ? $type : 'rss');

		if (!($renderer instanceof DocumentRenderer))
		{
			throw new \Exception(JText::_('JGLOBAL_RESOURCE_NOT_FOUND'),
404);
		}

		$this->setMimeEncoding($renderer->getContentType());

		// Output
		// Generate prolog
		$data = "<?xml version=\"1.0\" encoding=\"" .
$this->_charset . "\"?>\n";
		$data .= "<!-- generator=\"" . $this->getGenerator()
. "\" -->\n";

		// Generate stylesheet links
		foreach ($this->_styleSheets as $src => $attr)
		{
			$data .= "<?xml-stylesheet href=\"$src\"
type=\"" . $attr['type'] . "\"?>\n";
		}

		// Render the feed
		$data .= $renderer->render();

		parent::render($cache, $params);

		return $data;
	}

	/**
	 * Adds a FeedItem to the feed.
	 *
	 * @param   FeedItem  $item  The feeditem to add to the feed.
	 *
	 * @return  FeedDocument  instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function addItem(FeedItem $item)
	{
		$item->source = $this->link;
		$this->items[] = $item;

		return $this;
	}
}
HtmlDocument.php000064400000047002151157371000007663 0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Cache\Cache;
use Joomla\CMS\Helper\ModuleHelper;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Uri\Uri;
use Joomla\Registry\Registry;

jimport('joomla.utilities.utility');

/**
 * HtmlDocument class, provides an easy interface to parse and display a
HTML document
 *
 * @since  1.7.0
 */
class HtmlDocument extends Document
{
	/**
	 * Array of Header `<link>` tags
	 *
	 * @var    array
	 * @since  1.7.0
	 */
	public $_links = array();

	/**
	 * Array of custom tags
	 *
	 * @var    array
	 * @since  1.7.0
	 */
	public $_custom = array();

	/**
	 * Name of the template
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $template = null;

	/**
	 * Base url
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $baseurl = null;

	/**
	 * Array of template parameters
	 *
	 * @var    array
	 * @since  1.7.0
	 */
	public $params = null;

	/**
	 * File name
	 *
	 * @var    array
	 * @since  1.7.0
	 */
	public $_file = null;

	/**
	 * String holding parsed template
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	protected $_template = '';

	/**
	 * Array of parsed template JDoc tags
	 *
	 * @var    array
	 * @since  1.7.0
	 */
	protected $_template_tags = array();

	/**
	 * Integer with caching setting
	 *
	 * @var    integer
	 * @since  1.7.0
	 */
	protected $_caching = null;

	/**
	 * Set to true when the document should be output as HTML5
	 *
	 * @var    boolean
	 * @since  3.0.0
	 *
	 * @note  4.0  Will be replaced by $html5 and the default value will be
true.
	 */
	private $_html5 = null;

	/**
	 * Class constructor
	 *
	 * @param   array  $options  Associative array of options
	 *
	 * @since   1.7.0
	 */
	public function __construct($options = array())
	{
		parent::__construct($options);

		// Set document type
		$this->_type = 'html';

		// Set default mime type and document metadata (metadata syncs with mime
type by default)
		$this->setMimeEncoding('text/html');
	}

	/**
	 * Get the HTML document head data
	 *
	 * @return  array  The document head data in array form
	 *
	 * @since   1.7.0
	 */
	public function getHeadData()
	{
		$data = array();
		$data['title']         = $this->title;
		$data['description']   = $this->description;
		$data['link']          = $this->link;
		$data['metaTags']      = $this->_metaTags;
		$data['links']         = $this->_links;
		$data['styleSheets']   = $this->_styleSheets;
		$data['style']         = $this->_style;
		$data['scripts']       = $this->_scripts;
		$data['script']        = $this->_script;
		$data['custom']        = $this->_custom;

		// This is for b.c. and can be safely removed in future
		$data['scriptText']    = \JText::getScriptStrings();

		$data['scriptOptions'] = $this->scriptOptions;

		return $data;
	}

	/**
	 * Reset the HTML document head data
	 *
	 * @param   mixed  $types  type or types of the heads elements to reset
	 *
	 * @return  HtmlDocument  instance of $this to allow chaining
	 *
	 * @since   3.7.0
	 */
	public function resetHeadData($types = null)
	{
		if (is_null($types))
		{
			$this->title         = '';
			$this->description   = '';
			$this->link          = '';
			$this->_metaTags     = array();
			$this->_links        = array();
			$this->_styleSheets  = array();
			$this->_style        = array();
			$this->_scripts      = array();
			$this->_script       = array();
			$this->_custom       = array();
			$this->scriptOptions = array();
		}

		if (is_array($types))
		{
			foreach ($types as $type)
			{
				$this->resetHeadDatum($type);
			}
		}

		if (is_string($types))
		{
			$this->resetHeadDatum($types);
		}

		return $this;
	}

	/**
	 * Reset a part the HTML document head data
	 *
	 * @param   string  $type  type of the heads elements to reset
	 *
	 * @return  void
	 *
	 * @since   3.7.0
	 */
	private function resetHeadDatum($type)
	{
		switch ($type)
		{
			case 'title':
			case 'description':
			case 'link':
				$this->{$type} = '';
				break;

			case 'metaTags':
			case 'links':
			case 'styleSheets':
			case 'style':
			case 'scripts':
			case 'script':
			case 'custom':
				$realType = '_' . $type;
				$this->{$realType} = array();
				break;

			case 'scriptOptions':
				$this->{$type} = array();
				break;
		}
	}

	/**
	 * Set the HTML document head data
	 *
	 * @param   array  $data  The document head data in array form
	 *
	 * @return  HtmlDocument|null instance of $this to allow chaining or null
for empty input data
	 *
	 * @since   1.7.0
	 */
	public function setHeadData($data)
	{
		if (empty($data) || !is_array($data))
		{
			return null;
		}

		$this->title         = (isset($data['title']) &&
!empty($data['title'])) ? $data['title'] :
$this->title;
		$this->description   = (isset($data['description'])
&& !empty($data['description'])) ?
$data['description'] : $this->description;
		$this->link          = (isset($data['link']) &&
!empty($data['link'])) ? $data['link'] :
$this->link;
		$this->_metaTags     = (isset($data['metaTags']) &&
!empty($data['metaTags'])) ? $data['metaTags'] :
$this->_metaTags;
		$this->_links        = (isset($data['links']) &&
!empty($data['links'])) ? $data['links'] :
$this->_links;
		$this->_styleSheets  = (isset($data['styleSheets'])
&& !empty($data['styleSheets'])) ?
$data['styleSheets'] : $this->_styleSheets;
		$this->_style        = (isset($data['style']) &&
!empty($data['style'])) ? $data['style'] :
$this->_style;
		$this->_scripts      = (isset($data['scripts']) &&
!empty($data['scripts'])) ? $data['scripts'] :
$this->_scripts;
		$this->_script       = (isset($data['script']) &&
!empty($data['script'])) ? $data['script'] :
$this->_script;
		$this->_custom       = (isset($data['custom']) &&
!empty($data['custom'])) ? $data['custom'] :
$this->_custom;
		$this->scriptOptions = (isset($data['scriptOptions'])
&& !empty($data['scriptOptions'])) ?
$data['scriptOptions'] : $this->scriptOptions;

		return $this;
	}

	/**
	 * Merge the HTML document head data
	 *
	 * @param   array  $data  The document head data in array form
	 *
	 * @return  HtmlDocument|null instance of $this to allow chaining or null
for empty input data
	 *
	 * @since   1.7.0
	 */
	public function mergeHeadData($data)
	{
		if (empty($data) || !is_array($data))
		{
			return;
		}

		$this->title = (isset($data['title']) &&
!empty($data['title']) && !stristr($this->title,
$data['title']))
			? $this->title . $data['title']
			: $this->title;
		$this->description = (isset($data['description']) &&
!empty($data['description']) &&
!stristr($this->description, $data['description']))
			? $this->description . $data['description']
			: $this->description;
		$this->link = (isset($data['link'])) ?
$data['link'] : $this->link;

		if (isset($data['metaTags']))
		{
			foreach ($data['metaTags'] as $type1 => $data1)
			{
				$booldog = $type1 == 'http-equiv' ? true : false;

				foreach ($data1 as $name2 => $data2)
				{
					$this->setMetaData($name2, $data2, $booldog);
				}
			}
		}

		$this->_links = (isset($data['links']) &&
!empty($data['links']) &&
is_array($data['links']))
			? array_unique(array_merge($this->_links, $data['links']),
SORT_REGULAR)
			: $this->_links;
		$this->_styleSheets = (isset($data['styleSheets'])
&& !empty($data['styleSheets']) &&
is_array($data['styleSheets']))
			? array_merge($this->_styleSheets, $data['styleSheets'])
			: $this->_styleSheets;

		if (isset($data['style']))
		{
			foreach ($data['style'] as $type => $stdata)
			{
				if (!isset($this->_style[strtolower($type)]) || !stristr($stdata,
$this->_style[strtolower($type)]))
				{
					$this->addStyleDeclaration($stdata, $type);
				}
			}
		}

		$this->_scripts = (isset($data['scripts']) &&
!empty($data['scripts']) &&
is_array($data['scripts']))
			? array_merge($this->_scripts, $data['scripts'])
			: $this->_scripts;

		if (isset($data['script']))
		{
			foreach ($data['script'] as $type => $sdata)
			{
				if (!isset($this->_script[strtolower($type)]) || !stristr($sdata,
$this->_script[strtolower($type)]))
				{
					$this->addScriptDeclaration($sdata, $type);
				}
			}
		}

		$this->_custom = (isset($data['custom']) &&
!empty($data['custom']) &&
is_array($data['custom']))
			? array_unique(array_merge($this->_custom,
$data['custom']))
			: $this->_custom;

		if (!empty($data['scriptOptions']))
		{
			foreach ($data['scriptOptions'] as $key => $scriptOptions)
			{
				$this->addScriptOptions($key, $scriptOptions, true);
			}
		}

		return $this;
	}

	/**
	 * Adds `<link>` tags to the head of the document
	 *
	 * $relType defaults to 'rel' as it is the most common relation
type used.
	 * ('rev' refers to reverse relation, 'rel' indicates
normal, forward relation.)
	 * Typical tag: `<link href="index.php"
rel="Start">`
	 *
	 * @param   string  $href      The link that is being related.
	 * @param   string  $relation  Relation of link.
	 * @param   string  $relType   Relation type attribute.  Either rel or rev
(default: 'rel').
	 * @param   array   $attribs   Associative array of remaining attributes.
	 *
	 * @return  HtmlDocument instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function addHeadLink($href, $relation, $relType = 'rel',
$attribs = array())
	{
		$this->_links[$href]['relation'] = $relation;
		$this->_links[$href]['relType'] = $relType;
		$this->_links[$href]['attribs'] = $attribs;

		return $this;
	}

	/**
	 * Adds a shortcut icon (favicon)
	 *
	 * This adds a link to the icon shown in the favorites list or on
	 * the left of the url in the address bar. Some browsers display
	 * it on the tab, as well.
	 *
	 * @param   string  $href      The link that is being related.
	 * @param   string  $type      File type
	 * @param   string  $relation  Relation of link
	 *
	 * @return  HtmlDocument instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function addFavicon($href, $type =
'image/vnd.microsoft.icon', $relation = 'shortcut
icon')
	{
		$href = str_replace('\\', '/', $href);
		$this->addHeadLink($href, $relation, 'rel',
array('type' => $type));

		return $this;
	}

	/**
	 * Adds a custom HTML string to the head block
	 *
	 * @param   string  $html  The HTML to add to the head
	 *
	 * @return  HtmlDocument instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function addCustomTag($html)
	{
		$this->_custom[] = trim($html);

		return $this;
	}

	/**
	 * Returns whether the document is set up to be output as HTML5
	 *
	 * @return  boolean true when HTML5 is used
	 *
	 * @since   3.0.0
	 */
	public function isHtml5()
	{
		return $this->_html5;
	}

	/**
	 * Sets whether the document should be output as HTML5
	 *
	 * @param   bool  $state  True when HTML5 should be output
	 *
	 * @return  void
	 *
	 * @since   3.0.0
	 */
	public function setHtml5($state)
	{
		if (is_bool($state))
		{
			$this->_html5 = $state;
		}
	}

	/**
	 * Get the contents of a document include
	 *
	 * @param   string  $type     The type of renderer
	 * @param   string  $name     The name of the element to render
	 * @param   array   $attribs  Associative array of remaining attributes.
	 *
	 * @return  mixed|string The output of the renderer
	 *
	 * @since   1.7.0
	 */
	public function getBuffer($type = null, $name = null, $attribs = array())
	{
		// If no type is specified, return the whole buffer
		if ($type === null)
		{
			return parent::$_buffer;
		}

		$title = (isset($attribs['title'])) ?
$attribs['title'] : null;

		if (isset(parent::$_buffer[$type][$name][$title]))
		{
			return parent::$_buffer[$type][$name][$title];
		}

		$renderer = $this->loadRenderer($type);

		if ($this->_caching == true && $type == 'modules')
		{
			$cache = \JFactory::getCache('com_modules', '');
			$hash = md5(serialize(array($name, $attribs, null, $renderer)));
			$cbuffer = $cache->get('cbuffer_' . $type);

			if (isset($cbuffer[$hash]))
			{
				return Cache::getWorkarounds($cbuffer[$hash],
array('mergehead' => 1));
			}
			else
			{
				$options = array();
				$options['nopathway'] = 1;
				$options['nomodules'] = 1;
				$options['modulemode'] = 1;

				$this->setBuffer($renderer->render($name, $attribs, null), $type,
$name);
				$data = parent::$_buffer[$type][$name][$title];

				$tmpdata = Cache::setWorkarounds($data, $options);

				$cbuffer[$hash] = $tmpdata;

				$cache->store($cbuffer, 'cbuffer_' . $type);
			}
		}
		else
		{
			$this->setBuffer($renderer->render($name, $attribs, null), $type,
$name, $title);
		}

		return parent::$_buffer[$type][$name][$title];
	}

	/**
	 * Set the contents a document includes
	 *
	 * @param   string  $content  The content to be set in the buffer.
	 * @param   array   $options  Array of optional elements.
	 *
	 * @return  HtmlDocument instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function setBuffer($content, $options = array())
	{
		// The following code is just for backward compatibility.
		if (func_num_args() > 1 && !is_array($options))
		{
			$args = func_get_args();
			$options = array();
			$options['type'] = $args[1];
			$options['name'] = (isset($args[2])) ? $args[2] : null;
			$options['title'] = (isset($args[3])) ? $args[3] : null;
		}

		parent::$_buffer[$options['type']][$options['name']][$options['title']]
= $content;

		return $this;
	}

	/**
	 * Parses the template and populates the buffer
	 *
	 * @param   array  $params  Parameters for fetching the template
	 *
	 * @return  HtmlDocument instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function parse($params = array())
	{
		return $this->_fetchTemplate($params)->_parseTemplate();
	}

	/**
	 * Outputs the template to the browser.
	 *
	 * @param   boolean  $caching  If true, cache the output
	 * @param   array    $params   Associative array of attributes
	 *
	 * @return  string The rendered data
	 *
	 * @since   1.7.0
	 */
	public function render($caching = false, $params = array())
	{
		$this->_caching = $caching;

		if (empty($this->_template))
		{
			$this->parse($params);
		}

		$data = $this->_renderTemplate();
		parent::render($caching, $params);

		return $data;
	}

	/**
	 * Count the modules based on the given condition
	 *
	 * @param   string  $condition  The condition to use
	 *
	 * @return  integer  Number of modules found
	 *
	 * @since   1.7.0
	 */
	public function countModules($condition)
	{
		$operators =
'(\+|\-|\*|\/|==|\!=|\<\>|\<|\>|\<=|\>=|and|or|xor)';
		$words = preg_split('# ' . $operators . ' #',
$condition, null, PREG_SPLIT_DELIM_CAPTURE);

		if (count($words) === 1)
		{
			$name = strtolower($words[0]);
			$result = ((isset(parent::$_buffer['modules'][$name]))
&& (parent::$_buffer['modules'][$name] === false))
				? 0 : count(ModuleHelper::getModules($name));

			return $result;
		}

		Log::add('Using an expression in HtmlDocument::countModules() is
deprecated.', Log::WARNING, 'deprecated');

		for ($i = 0, $n = count($words); $i < $n; $i += 2)
		{
			// Odd parts (modules)
			$name = strtolower($words[$i]);
			$words[$i] = ((isset(parent::$_buffer['modules'][$name]))
&& (parent::$_buffer['modules'][$name] === false))
				? 0
				: count(ModuleHelper::getModules($name));
		}

		$str = 'return ' . implode(' ', $words) .
';';

		return eval($str);
	}

	/**
	 * Count the number of child menu items of the current active menu item
	 *
	 * @return  integer  Number of child menu items
	 *
	 * @since   1.7.0
	 */
	public function countMenuChildren()
	{
		static $children;

		if (!isset($children))
		{
			$db = \JFactory::getDbo();
			$app = \JFactory::getApplication();
			$menu = $app->getMenu();
			$active = $menu->getActive();
			$children = 0;

			if ($active)
			{
				$query = $db->getQuery(true)
					->select('COUNT(*)')
					->from('#__menu')
					->where('parent_id = ' . $active->id)
					->where('published = 1');
				$db->setQuery($query);
				$children = $db->loadResult();
			}
		}

		return $children;
	}

	/**
	 * Load a template file
	 *
	 * @param   string  $directory  The name of the template
	 * @param   string  $filename   The actual filename
	 *
	 * @return  string  The contents of the template
	 *
	 * @since   1.7.0
	 */
	protected function _loadTemplate($directory, $filename)
	{
		$contents = '';

		// Check to see if we have a valid template file
		if (file_exists($directory . '/' . $filename))
		{
			// Store the file path
			$this->_file = $directory . '/' . $filename;

			// Get the file content
			ob_start();
			require $directory . '/' . $filename;
			$contents = ob_get_contents();
			ob_end_clean();
		}

		// Try to find a favicon by checking the template and root folder
		$icon = '/favicon.ico';

		foreach (array($directory, JPATH_BASE) as $dir)
		{
			if (file_exists($dir . $icon))
			{
				$path = str_replace(JPATH_BASE, '', $dir);
				$path = str_replace('\\', '/', $path);
				$this->addFavicon(Uri::base(true) . $path . $icon);
				break;
			}
		}

		return $contents;
	}

	/**
	 * Fetch the template, and initialise the params
	 *
	 * @param   array  $params  Parameters to determine the template
	 *
	 * @return  HtmlDocument instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	protected function _fetchTemplate($params = array())
	{
		// Check
		$directory = isset($params['directory']) ?
$params['directory'] : 'templates';
		$filter = \JFilterInput::getInstance();
		$template = $filter->clean($params['template'],
'cmd');
		$file = $filter->clean($params['file'], 'cmd');

		if (!file_exists($directory . '/' . $template . '/' .
$file))
		{
			$template = 'system';
		}

		if (!file_exists($directory . '/' . $template . '/' .
$file))
		{
			$file = 'index.php';
		}

		// Load the language file for the template
		$lang = \JFactory::getLanguage();

		// 1.5 or core then 1.6
		$lang->load('tpl_' . $template, JPATH_BASE, null, false,
true)
			|| $lang->load('tpl_' . $template, $directory .
'/' . $template, null, false, true);

		// Assign the variables
		$this->template = $template;
		$this->baseurl = Uri::base(true);
		$this->params = isset($params['params']) ?
$params['params'] : new Registry;

		// Load
		$this->_template = $this->_loadTemplate($directory . '/'
. $template, $file);

		return $this;
	}

	/**
	 * Parse a document template
	 *
	 * @return  HtmlDocument  instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	protected function _parseTemplate()
	{
		$matches = array();

		if (preg_match_all('#<jdoc:include\
type="([^"]+)"(.*)\/>#iU', $this->_template,
$matches))
		{
			$template_tags_first = array();
			$template_tags_last = array();

			// Step through the jdocs in reverse order.
			for ($i = count($matches[0]) - 1; $i >= 0; $i--)
			{
				$type = $matches[1][$i];
				$attribs = empty($matches[2][$i]) ? array() :
\JUtility::parseAttributes($matches[2][$i]);
				$name = isset($attribs['name']) ? $attribs['name']
: null;

				// Separate buffers to be executed first and last
				if ($type == 'module' || $type == 'modules')
				{
					$template_tags_first[$matches[0][$i]] = array('type' =>
$type, 'name' => $name, 'attribs' => $attribs);
				}
				else
				{
					$template_tags_last[$matches[0][$i]] = array('type' =>
$type, 'name' => $name, 'attribs' => $attribs);
				}
			}

			// Reverse the last array so the jdocs are in forward order.
			$template_tags_last = array_reverse($template_tags_last);

			$this->_template_tags = $template_tags_first + $template_tags_last;
		}

		return $this;
	}

	/**
	 * Render pre-parsed template
	 *
	 * @return string rendered template
	 *
	 * @since   1.7.0
	 */
	protected function _renderTemplate()
	{
		$replace = array();
		$with = array();

		foreach ($this->_template_tags as $jdoc => $args)
		{
			$replace[] = $jdoc;
			$with[] = $this->getBuffer($args['type'],
$args['name'], $args['attribs']);
		}

		return str_replace($replace, $with, $this->_template);
	}
}
ImageDocument.php000064400000002636151157371000010005 0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document;

defined('JPATH_PLATFORM') or die;

/**
 * ImageDocument class, provides an easy interface to output image data
 *
 * @since  3.0.0
 */
class ImageDocument extends Document
{
	/**
	 * Class constructor
	 *
	 * @param   array  $options  Associative array of options
	 *
	 * @since   3.0.0
	 */
	public function __construct($options = array())
	{
		parent::__construct($options);

		// Set mime type
		$this->_mime = 'image/png';

		// Set document type
		$this->_type = 'image';
	}

	/**
	 * Render the document.
	 *
	 * @param   boolean  $cache   If true, cache the output
	 * @param   array    $params  Associative array of attributes
	 *
	 * @return  string  The rendered data
	 *
	 * @since   3.0.0
	 */
	public function render($cache = false, $params = array())
	{
		// Get the image type
		$type = \JFactory::getApplication()->input->get('type',
'png');

		switch ($type)
		{
			case 'jpg':
			case 'jpeg':
				$this->_mime = 'image/jpeg';
				break;
			case 'gif':
				$this->_mime = 'image/gif';
				break;
			case 'png':
			default:
				$this->_mime = 'image/png';
				break;
		}

		$this->_charset = null;

		parent::render($cache, $params);

		return $this->getBuffer();
	}
}
JsonDocument.php000064400000004262151157371000007671 0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document;

defined('JPATH_PLATFORM') or die;

/**
 * JsonDocument class, provides an easy interface to parse and display JSON
output
 *
 * @link   http://www.json.org/
 * @since  1.7.0
 */
class JsonDocument extends Document
{
	/**
	 * Document name
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	protected $_name = 'joomla';

	/**
	 * Class constructor
	 *
	 * @param   array  $options  Associative array of options
	 *
	 * @since  1.7.0
	 */
	public function __construct($options = array())
	{
		parent::__construct($options);

		// Set mime type
		if (isset($_SERVER['HTTP_ACCEPT'])
			&& strpos($_SERVER['HTTP_ACCEPT'],
'application/json') === false
			&& strpos($_SERVER['HTTP_ACCEPT'],
'text/html') !== false)
		{
			// Internet Explorer < 10
			$this->_mime = 'text/plain';
		}
		else
		{
			$this->_mime = 'application/json';
		}

		// Set document type
		$this->_type = 'json';
	}

	/**
	 * Render the document.
	 *
	 * @param   boolean  $cache   If true, cache the output
	 * @param   array    $params  Associative array of attributes
	 *
	 * @return  string  The rendered data
	 *
	 * @since  1.7.0
	 */
	public function render($cache = false, $params = array())
	{
		/** @var \Joomla\CMS\Application\CMSApplication $app **/
		$app = \JFactory::getApplication();

		$app->allowCache($cache);

		if ($this->_mime == 'application/json')
		{
			// Browser other than Internet Explorer < 10
			$app->setHeader('Content-Disposition', 'attachment;
filename="' . $this->getName() . '.json"',
true);
		}

		parent::render($cache, $params);

		return $this->getBuffer();
	}

	/**
	 * Returns the document name
	 *
	 * @return  string
	 *
	 * @since  1.7.0
	 */
	public function getName()
	{
		return $this->_name;
	}

	/**
	 * Sets the document name
	 *
	 * @param   string  $name  Document name
	 *
	 * @return  JsonDocument instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function setName($name = 'joomla')
	{
		$this->_name = $name;

		return $this;
	}
}
Opensearch/OpensearchImage.php000064400000001555151157371000012404
0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document\Opensearch;

defined('JPATH_PLATFORM') or die;

/**
 * Data object representing an OpenSearch image
 *
 * @since  1.7.0
 */
class OpensearchImage
{
	/**
	 * The images MIME type
	 *
	 * required
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $type = '';

	/**
	 * URL of the image or the image as base64 encoded value
	 *
	 * required
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $data = '';

	/**
	 * The image's width
	 *
	 * required
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $width;

	/**
	 * The image's height
	 *
	 * required
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $height;
}
Opensearch/OpensearchUrl.php000064400000001437151157371000012123
0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document\Opensearch;

defined('JPATH_PLATFORM') or die;

/**
 * Data object representing an OpenSearch URL
 *
 * @since  1.7.0
 */
class OpensearchUrl
{
	/**
	 * Type item element
	 *
	 * required
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $type = 'text/html';

	/**
	 * Rel item element
	 *
	 * required
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $rel = 'results';

	/**
	 * Template item element. Has to contain the {searchTerms} parameter to
work.
	 *
	 * required
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	public $template;
}
OpensearchDocument.php000064400000012224151157371000011044 0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Document\Opensearch\OpensearchImage;
use Joomla\CMS\Document\Opensearch\OpensearchUrl;
use Joomla\CMS\Uri\Uri;

/**
 * Opensearch class, provides an easy interface to display an Opensearch
document
 *
 * @link   http://www.opensearch.org/
 * @since  1.7.0
 */
class OpensearchDocument extends Document
{
	/**
	 * ShortName element
	 *
	 * required
	 *
	 * @var    string
	 * @since  1.7.0
	 */
	private $_shortName = '';

	/**
	 * Images collection
	 *
	 * optional
	 *
	 * @var    object
	 * @since  1.7.0
	 */
	private $_images = array();

	/**
	 * The url collection
	 *
	 * @var    array
	 * @since  1.7.0
	 */
	private $_urls = array();

	/**
	 * Class constructor
	 *
	 * @param   array  $options  Associative array of options
	 *
	 * @since  1.7.0
	 */
	public function __construct($options = array())
	{
		parent::__construct($options);

		// Set document type
		$this->_type = 'opensearch';

		// Set mime type
		$this->_mime = 'application/opensearchdescription+xml';

		// Add the URL for self updating
		$update = new OpensearchUrl;
		$update->type = 'application/opensearchdescription+xml';
		$update->rel = 'self';
		$update->template = \JRoute::_(Uri::getInstance());
		$this->addUrl($update);

		// Add the favicon as the default image
		// Try to find a favicon by checking the template and root folder
		$app = \JFactory::getApplication();
		$dirs = array(JPATH_THEMES . '/' . $app->getTemplate(),
JPATH_BASE);

		foreach ($dirs as $dir)
		{
			if (file_exists($dir . '/favicon.ico'))
			{
				$path = str_replace(JPATH_BASE, '', $dir);
				$path = str_replace('\\', '/', $path);
				$favicon = new OpensearchImage;

				if ($path == '')
				{
					$favicon->data = Uri::base() . 'favicon.ico';
				}
				else
				{
					if ($path[0] == '/')
					{
						$path = substr($path, 1);
					}

					$favicon->data = Uri::base() . $path . '/favicon.ico';
				}

				$favicon->height = '16';
				$favicon->width = '16';
				$favicon->type = 'image/vnd.microsoft.icon';

				$this->addImage($favicon);

				break;
			}
		}
	}

	/**
	 * Render the document
	 *
	 * @param   boolean  $cache   If true, cache the output
	 * @param   array    $params  Associative array of attributes
	 *
	 * @return  string  The rendered data
	 *
	 * @since   1.7.0
	 */
	public function render($cache = false, $params = array())
	{
		$xml = new \DOMDocument('1.0', 'utf-8');

		if (defined('JDEBUG') && JDEBUG)
		{
			$xml->formatOutput = true;
		}

		// The Opensearch Namespace
		$osns = 'http://a9.com/-/spec/opensearch/1.1/';

		// Create the root element
		$elOs = $xml->createElementNs($osns,
'OpenSearchDescription');

		$elShortName = $xml->createElementNs($osns, 'ShortName');
		$elShortName->appendChild($xml->createTextNode(htmlspecialchars($this->_shortName)));
		$elOs->appendChild($elShortName);

		$elDescription = $xml->createElementNs($osns,
'Description');
		$elDescription->appendChild($xml->createTextNode(htmlspecialchars($this->description)));
		$elOs->appendChild($elDescription);

		// Always set the accepted input encoding to UTF-8
		$elInputEncoding = $xml->createElementNs($osns,
'InputEncoding');
		$elInputEncoding->appendChild($xml->createTextNode('UTF-8'));
		$elOs->appendChild($elInputEncoding);

		foreach ($this->_images as $image)
		{
			$elImage = $xml->createElementNs($osns, 'Image');
			$elImage->setAttribute('type', $image->type);
			$elImage->setAttribute('width', $image->width);
			$elImage->setAttribute('height', $image->height);
			$elImage->appendChild($xml->createTextNode(htmlspecialchars($image->data)));
			$elOs->appendChild($elImage);
		}

		foreach ($this->_urls as $url)
		{
			$elUrl = $xml->createElementNs($osns, 'Url');
			$elUrl->setAttribute('type', $url->type);

			// Results is the default value so we don't need to add it
			if ($url->rel != 'results')
			{
				$elUrl->setAttribute('rel', $url->rel);
			}

			$elUrl->setAttribute('template', $url->template);
			$elOs->appendChild($elUrl);
		}

		$xml->appendChild($elOs);
		parent::render($cache, $params);

		return $xml->saveXml();
	}

	/**
	 * Sets the short name
	 *
	 * @param   string  $name  The name.
	 *
	 * @return  OpensearchDocument instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function setShortName($name)
	{
		$this->_shortName = $name;

		return $this;
	}

	/**
	 * Adds a URL to the Opensearch description.
	 *
	 * @param   OpensearchUrl  $url  The url to add to the description.
	 *
	 * @return  OpensearchDocument instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function addUrl(OpensearchUrl $url)
	{
		$this->_urls[] = $url;

		return $this;
	}

	/**
	 * Adds an image to the Opensearch description.
	 *
	 * @param   OpensearchImage  $image  The image to add to the description.
	 *
	 * @return  OpensearchDocument instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function addImage(OpensearchImage $image)
	{
		$this->_images[] = $image;

		return $this;
	}
}
RawDocument.php000064400000002110151157371000007477 0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document;

defined('JPATH_PLATFORM') or die;

/**
 * RawDocument class, provides an easy interface to parse and display raw
output
 *
 * @since  1.7.0
 */
class RawDocument extends Document
{
	/**
	 * Class constructor
	 *
	 * @param   array  $options  Associative array of options
	 *
	 * @since   1.7.0
	 */
	public function __construct($options = array())
	{
		parent::__construct($options);

		// Set mime type
		$this->_mime = 'text/html';

		// Set document type
		$this->_type = 'raw';
	}

	/**
	 * Render the document.
	 *
	 * @param   boolean  $cache   If true, cache the output
	 * @param   array    $params  Associative array of attributes
	 *
	 * @return  string  The rendered data
	 *
	 * @since   1.7.0
	 */
	public function render($cache = false, $params = array())
	{
		parent::render($cache, $params);

		return $this->getBuffer();
	}
}
Renderer/Feed/AtomRenderer.php000064400000014760151157371000012265
0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document\Renderer\Feed;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Document\DocumentRenderer;
use Joomla\CMS\Uri\Uri;

/**
 * AtomRenderer is a feed that implements the atom specification
 *
 * Please note that just by using this class you won't automatically
 * produce valid atom files. For example, you have to specify either an
editor
 * for the feed or an author for every single feed item.
 *
 * @link  
http://www.atomenabled.org/developers/syndication/atom-format-spec.php
 * @since  3.5
 *
 * @property-read  \Joomla\CMS\Document\FeedDocument  $_doc  Reference to
the Document object that instantiated the renderer
 */
class AtomRenderer extends DocumentRenderer
{
	/**
	 * Document mime type
	 *
	 * @var    string
	 * @since  3.5
	 */
	protected $_mime = 'application/atom+xml';

	/**
	 * Render the feed.
	 *
	 * @param   string  $name     The name of the element to render
	 * @param   array   $params   Array of values
	 * @param   string  $content  Override the output of the renderer
	 *
	 * @return  string  The output of the script
	 *
	 * @see     DocumentRenderer::render()
	 * @since   3.5
	 */
	public function render($name = '', $params = null, $content =
null)
	{
		$app = \JFactory::getApplication();

		// Gets and sets timezone offset from site configuration
		$tz  = new \DateTimeZone($app->get('offset'));
		$now = \JFactory::getDate();
		$now->setTimeZone($tz);

		$data = $this->_doc;

		$url = Uri::getInstance()->toString(array('scheme',
'user', 'pass', 'host', 'port'));
		$syndicationURL = \JRoute::_('&format=feed&type=atom');

		$title = $data->getTitle();

		if ($app->get('sitename_pagetitles', 0) == 1)
		{
			$title = \JText::sprintf('JPAGETITLE',
$app->get('sitename'), $data->getTitle());
		}
		elseif ($app->get('sitename_pagetitles', 0) == 2)
		{
			$title = \JText::sprintf('JPAGETITLE', $data->getTitle(),
$app->get('sitename'));
		}

		$feed_title = htmlspecialchars($title, ENT_COMPAT, 'UTF-8');

		$feed = "<feed xmlns=\"http://www.w3.org/2005/Atom\"
";

		if ($data->getLanguage() != '')
		{
			$feed .= " xml:lang=\"" . $data->getLanguage() .
"\"";
		}

		$feed .= ">\n";
		$feed .= "	<title type=\"text\">" . $feed_title
. "</title>\n";
		$feed .= "	<subtitle type=\"text\">" .
htmlspecialchars($data->getDescription(), ENT_COMPAT, 'UTF-8')
. "</subtitle>\n";

		if (!empty($data->category))
		{
			if (is_array($data->category))
			{
				foreach ($data->category as $cat)
				{
					$feed .= "	<category term=\"" .
htmlspecialchars($cat, ENT_COMPAT, 'UTF-8') . "\"
/>\n";
				}
			}
			else
			{
				$feed .= "	<category term=\"" .
htmlspecialchars($data->category, ENT_COMPAT, 'UTF-8') .
"\" />\n";
			}
		}

		$feed .= "	<link rel=\"alternate\"
type=\"text/html\" href=\"" . $url .
"\"/>\n";
		$feed .= "	<id>" . str_replace(' ',
'%20', $data->getBase()) . "</id>\n";
		$feed .= "	<updated>" .
htmlspecialchars($now->toISO8601(true), ENT_COMPAT, 'UTF-8') .
"</updated>\n";

		if ($data->editor != '')
		{
			$feed .= "	<author>\n";
			$feed .= "		<name>" . $data->editor .
"</name>\n";

			if ($data->editorEmail != '')
			{
				$feed .= "		<email>" .
htmlspecialchars($data->editorEmail, ENT_COMPAT, 'UTF-8') .
"</email>\n";
			}

			$feed .= "	</author>\n";
		}

		$versionHtmlEscaped = '';

		if ($app->get('MetaVersion', 0))
		{
			$minorVersion       = \JVersion::MAJOR_VERSION . '.' .
\JVersion::MINOR_VERSION;
			$versionHtmlEscaped = ' version="' .
htmlspecialchars($minorVersion, ENT_COMPAT, 'UTF-8') .
'"';
		}

		$feed .= "	<generator
uri=\"https://www.joomla.org\"" . $versionHtmlEscaped .
">" . $data->getGenerator() .
"</generator>\n";
		$feed .= "	<link rel=\"self\"
type=\"application/atom+xml\" href=\"" .
str_replace(' ', '%20', $url . $syndicationURL) .
"\"/>\n";

		for ($i = 0, $count = count($data->items); $i < $count; $i++)
		{
			$itemlink = $data->items[$i]->link;

			if (preg_match('/[\x80-\xFF]/', $itemlink))
			{
				$itemlink = implode('/', array_map('rawurlencode',
explode('/', $itemlink)));
			}

			$feed .= "	<entry>\n";
			$feed .= "		<title>" .
htmlspecialchars(strip_tags($data->items[$i]->title), ENT_COMPAT,
'UTF-8') . "</title>\n";
			$feed .= "		<link rel=\"alternate\"
type=\"text/html\" href=\"" . $url . $itemlink .
"\"/>\n";

			if ($data->items[$i]->date == '')
			{
				$data->items[$i]->date = $now->toUnix();
			}

			$itemDate = \JFactory::getDate($data->items[$i]->date);
			$itemDate->setTimeZone($tz);
			$feed .= "		<published>" .
htmlspecialchars($itemDate->toISO8601(true), ENT_COMPAT,
'UTF-8') . "</published>\n";
			$feed .= "		<updated>" .
htmlspecialchars($itemDate->toISO8601(true), ENT_COMPAT,
'UTF-8') . "</updated>\n";

			if (empty($data->items[$i]->guid))
			{
				$itemGuid = str_replace(' ', '%20', $url .
$itemlink);
			}
			else
			{
				$itemGuid = htmlspecialchars($data->items[$i]->guid, ENT_COMPAT,
'UTF-8');
			}

			$feed .= "		<id>" . $itemGuid .
"</id>\n";

			if ($data->items[$i]->author != '')
			{
				$feed .= "		<author>\n";
				$feed .= "			<name>" .
htmlspecialchars($data->items[$i]->author, ENT_COMPAT,
'UTF-8') . "</name>\n";

				if (!empty($data->items[$i]->authorEmail))
				{
					$feed .= "			<email>" .
htmlspecialchars($data->items[$i]->authorEmail, ENT_COMPAT,
'UTF-8') . "</email>\n";
				}

				$feed .= "		</author>\n";
			}

			if (!empty($data->items[$i]->description))
			{
				$feed .= "		<summary type=\"html\">" .
htmlspecialchars($this->_relToAbs($data->items[$i]->description),
ENT_COMPAT, 'UTF-8') . "</summary>\n";
				$feed .= "		<content type=\"html\">" .
htmlspecialchars($this->_relToAbs($data->items[$i]->description),
ENT_COMPAT, 'UTF-8') . "</content>\n";
			}

			if (!empty($data->items[$i]->category))
			{
				if (is_array($data->items[$i]->category))
				{
					foreach ($data->items[$i]->category as $cat)
					{
						$feed .= "		<category term=\"" .
htmlspecialchars($cat, ENT_COMPAT, 'UTF-8') . "\"
/>\n";
					}
				}
				else
				{
					$feed .= "		<category term=\"" .
htmlspecialchars($data->items[$i]->category, ENT_COMPAT,
'UTF-8') . "\" />\n";
				}
			}

			if ($data->items[$i]->enclosure != null)
			{
				$feed .= "		<link rel=\"enclosure\"
href=\"" . $data->items[$i]->enclosure->url .
"\" type=\""
					. $data->items[$i]->enclosure->type . "\" 
length=\"" . $data->items[$i]->enclosure->length .
"\" />\n";
			}

			$feed .= "	</entry>\n";
		}

		$feed .= "</feed>\n";

		return $feed;
	}
}
Renderer/Feed/RssRenderer.php000064400000017615151157371000012136
0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document\Renderer\Feed;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Document\DocumentRenderer;
use Joomla\CMS\Uri\Uri;

/**
 * RssRenderer is a feed that implements RSS 2.0 Specification
 *
 * @link   http://www.rssboard.org/rss-specification
 * @since  3.5
 *
 * @property-read  \Joomla\CMS\Document\FeedDocument  $_doc  Reference to
the Document object that instantiated the renderer
 */
class RssRenderer extends DocumentRenderer
{
	/**
	 * Renderer mime type
	 *
	 * @var    string
	 * @since  3.5
	 */
	protected $_mime = 'application/rss+xml';

	/**
	 * Render the feed.
	 *
	 * @param   string  $name     The name of the element to render
	 * @param   array   $params   Array of values
	 * @param   string  $content  Override the output of the renderer
	 *
	 * @return  string  The output of the script
	 *
	 * @see     DocumentRenderer::render()
	 * @since   3.5
	 */
	public function render($name = '', $params = null, $content =
null)
	{
		$app = \JFactory::getApplication();

		// Gets and sets timezone offset from site configuration
		$tz  = new \DateTimeZone($app->get('offset'));
		$now = \JFactory::getDate();
		$now->setTimeZone($tz);

		$data = $this->_doc;

		$url = Uri::getInstance()->toString(array('scheme',
'user', 'pass', 'host', 'port'));
		$syndicationURL = \JRoute::_('&format=feed&type=rss');

		$title = $data->getTitle();

		if ($app->get('sitename_pagetitles', 0) == 1)
		{
			$title = \JText::sprintf('JPAGETITLE',
$app->get('sitename'), $data->getTitle());
		}
		elseif ($app->get('sitename_pagetitles', 0) == 2)
		{
			$title = \JText::sprintf('JPAGETITLE', $data->getTitle(),
$app->get('sitename'));
		}

		$feed_title = htmlspecialchars($title, ENT_COMPAT, 'UTF-8');

		$datalink = $data->getLink();

		if (preg_match('/[\x80-\xFF]/', $datalink))
		{
			$datalink = implode('/', array_map('rawurlencode',
explode('/', $datalink)));
		}

		$feed = "<rss version=\"2.0\"
xmlns:atom=\"http://www.w3.org/2005/Atom\">\n";
		$feed .= "	<channel>\n";
		$feed .= "		<title>" . $feed_title .
"</title>\n";
		$feed .= "		<description><![CDATA[" .
$data->getDescription() . "]]></description>\n";
		$feed .= "		<link>" . str_replace(' ',
'%20', $url . $datalink) . "</link>\n";
		$feed .= "		<lastBuildDate>" .
htmlspecialchars($now->toRFC822(true), ENT_COMPAT, 'UTF-8') .
"</lastBuildDate>\n";
		$feed .= "		<generator>" . $data->getGenerator() .
"</generator>\n";
		$feed .= "		<atom:link rel=\"self\"
type=\"application/rss+xml\" href=\"" .
str_replace(' ', '%20', $url . $syndicationURL) .
"\"/>\n";

		if ($data->image != null)
		{
			$feed .= "		<image>\n";
			$feed .= "			<url>" . $data->image->url .
"</url>\n";
			$feed .= "			<title>" .
htmlspecialchars($data->image->title, ENT_COMPAT, 'UTF-8')
. "</title>\n";
			$feed .= "			<link>" . str_replace(' ',
'%20', $data->image->link) . "</link>\n";

			if ($data->image->width != '')
			{
				$feed .= "			<width>" . $data->image->width .
"</width>\n";
			}

			if ($data->image->height != '')
			{
				$feed .= "			<height>" . $data->image->height .
"</height>\n";
			}

			if ($data->image->description != '')
			{
				$feed .= "			<description><![CDATA[" .
$data->image->description . "]]></description>\n";
			}

			$feed .= "		</image>\n";
		}

		if ($data->getLanguage() !== '')
		{
			$feed .= "		<language>" . $data->getLanguage() .
"</language>\n";
		}

		if ($data->copyright != '')
		{
			$feed .= "		<copyright>" .
htmlspecialchars($data->copyright, ENT_COMPAT, 'UTF-8') .
"</copyright>\n";
		}

		if ($data->editorEmail != '')
		{
			$feed .= "		<managingEditor>" .
htmlspecialchars($data->editorEmail, ENT_COMPAT, 'UTF-8') .
' ('
				. htmlspecialchars($data->editor, ENT_COMPAT, 'UTF-8') .
")</managingEditor>\n";
		}

		if ($data->webmaster != '')
		{
			$feed .= "		<webMaster>" .
htmlspecialchars($data->webmaster, ENT_COMPAT, 'UTF-8') .
"</webMaster>\n";
		}

		if ($data->pubDate != '')
		{
			$pubDate = \JFactory::getDate($data->pubDate);
			$pubDate->setTimeZone($tz);
			$feed .= "		<pubDate>" .
htmlspecialchars($pubDate->toRFC822(true), ENT_COMPAT,
'UTF-8') . "</pubDate>\n";
		}

		if (!empty($data->category))
		{
			if (is_array($data->category))
			{
				foreach ($data->category as $cat)
				{
					$feed .= "		<category>" . htmlspecialchars($cat,
ENT_COMPAT, 'UTF-8') . "</category>\n";
				}
			}
			else
			{
				$feed .= "		<category>" .
htmlspecialchars($data->category, ENT_COMPAT, 'UTF-8') .
"</category>\n";
			}
		}

		if ($data->docs != '')
		{
			$feed .= "		<docs>" . htmlspecialchars($data->docs,
ENT_COMPAT, 'UTF-8') . "</docs>\n";
		}

		if ($data->ttl != '')
		{
			$feed .= "		<ttl>" . htmlspecialchars($data->ttl,
ENT_COMPAT, 'UTF-8') . "</ttl>\n";
		}

		if ($data->rating != '')
		{
			$feed .= "		<rating>" .
htmlspecialchars($data->rating, ENT_COMPAT, 'UTF-8') .
"</rating>\n";
		}

		if ($data->skipHours != '')
		{
			$feed .= "		<skipHours>" .
htmlspecialchars($data->skipHours, ENT_COMPAT, 'UTF-8') .
"</skipHours>\n";
		}

		if ($data->skipDays != '')
		{
			$feed .= "		<skipDays>" .
htmlspecialchars($data->skipDays, ENT_COMPAT, 'UTF-8') .
"</skipDays>\n";
		}

		for ($i = 0, $count = count($data->items); $i < $count; $i++)
		{
			$itemlink = $data->items[$i]->link;

			if (preg_match('/[\x80-\xFF]/', $itemlink))
			{
				$itemlink = implode('/', array_map('rawurlencode',
explode('/', $itemlink)));
			}

			if ((strpos($itemlink, 'http://') === false) &&
(strpos($itemlink, 'https://') === false))
			{
				$itemlink = str_replace(' ', '%20', $url .
$itemlink);
			}

			$feed .= "		<item>\n";
			$feed .= "			<title>" .
htmlspecialchars(strip_tags($data->items[$i]->title), ENT_COMPAT,
'UTF-8') . "</title>\n";
			$feed .= "			<link>" . str_replace(' ',
'%20', $itemlink) . "</link>\n";

			if (empty($data->items[$i]->guid))
			{
				$feed .= "			<guid isPermaLink=\"true\">" .
str_replace(' ', '%20', $itemlink) .
"</guid>\n";
			}
			else
			{
				$feed .= "			<guid isPermaLink=\"false\">" .
htmlspecialchars($data->items[$i]->guid, ENT_COMPAT,
'UTF-8') . "</guid>\n";
			}

			$feed .= "			<description><![CDATA[" .
$this->_relToAbs($data->items[$i]->description) .
"]]></description>\n";

			if ($data->items[$i]->authorEmail != '')
			{
				$feed .= '			<author>'
					. htmlspecialchars($data->items[$i]->authorEmail . '
(' . $data->items[$i]->author . ')', ENT_COMPAT,
'UTF-8') . "</author>\n";
			}

			/*
			 * @todo: On hold
			 * if ($data->items[$i]->source!='')
			 * {
			 *   $data.= "			<source>" .
htmlspecialchars($data->items[$i]->source, ENT_COMPAT,
'UTF-8') . "</source>\n";
			 * }
			 */

			if (empty($data->items[$i]->category) === false)
			{
				if (is_array($data->items[$i]->category))
				{
					foreach ($data->items[$i]->category as $cat)
					{
						$feed .= "			<category>" . htmlspecialchars($cat,
ENT_COMPAT, 'UTF-8') . "</category>\n";
					}
				}
				else
				{
					$feed .= "			<category>" .
htmlspecialchars($data->items[$i]->category, ENT_COMPAT,
'UTF-8') . "</category>\n";
				}
			}

			if ($data->items[$i]->comments != '')
			{
				$feed .= "			<comments>" .
htmlspecialchars($data->items[$i]->comments, ENT_COMPAT,
'UTF-8') . "</comments>\n";
			}

			if ($data->items[$i]->date != '')
			{
				$itemDate = \JFactory::getDate($data->items[$i]->date);
				$itemDate->setTimeZone($tz);
				$feed .= "			<pubDate>" .
htmlspecialchars($itemDate->toRFC822(true), ENT_COMPAT,
'UTF-8') . "</pubDate>\n";
			}

			if ($data->items[$i]->enclosure != null)
			{
				$feed .= "			<enclosure url=\"";
				$feed .= $data->items[$i]->enclosure->url;
				$feed .= "\" length=\"";
				$feed .= $data->items[$i]->enclosure->length;
				$feed .= "\" type=\"";
				$feed .= $data->items[$i]->enclosure->type;
				$feed .= "\"/>\n";
			}

			$feed .= "		</item>\n";
		}

		$feed .= "	</channel>\n";
		$feed .= "</rss>\n";

		return $feed;
	}
}
Renderer/Html/ComponentRenderer.php000064400000001615151157371000013363
0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document\Renderer\Html;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Document\DocumentRenderer;

/**
 * HTML document renderer for the component output
 *
 * @since  3.5
 */
class ComponentRenderer extends DocumentRenderer
{
	/**
	 * Renders a component script and returns the results as a string
	 *
	 * @param   string  $component  The name of the component to render
	 * @param   array   $params     Associative array of values
	 * @param   string  $content    Content script
	 *
	 * @return  string  The output of the script
	 *
	 * @since   3.5
	 */
	public function render($component = null, $params = array(), $content =
null)
	{
		return $content;
	}
}
Renderer/Html/HeadRenderer.php000064400000025077151157371000012272
0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document\Renderer\Html;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Document\DocumentRenderer;
use Joomla\CMS\Helper\TagsHelper;
use Joomla\CMS\Uri\Uri;
use Joomla\Utilities\ArrayHelper;

/**
 * HTML document renderer for the document `<head>` element
 *
 * @since  3.5
 */
class HeadRenderer extends DocumentRenderer
{
	/**
	 * Renders the document head and returns the results as a string
	 *
	 * @param   string  $head     (unused)
	 * @param   array   $params   Associative array of values
	 * @param   string  $content  The script
	 *
	 * @return  string  The output of the script
	 *
	 * @since   3.5
	 */
	public function render($head, $params = array(), $content = null)
	{
		return $this->fetchHead($this->_doc);
	}

	/**
	 * Generates the head HTML and return the results as a string
	 *
	 * @param   JDocumentHtml  $document  The document for which the head will
be created
	 *
	 * @return  string  The head hTML
	 *
	 * @since   3.5
	 * @deprecated  4.0  Method code will be moved into the render method
	 */
	public function fetchHead($document)
	{
		// Convert the tagids to titles
		if (isset($document->_metaTags['name']['tags']))
		{
			$tagsHelper = new TagsHelper;
			$document->_metaTags['name']['tags'] =
implode(', ',
$tagsHelper->getTagNames($document->_metaTags['name']['tags']));
		}

		if ($document->getScriptOptions())
		{
			\JHtml::_('behavior.core');
		}

		// Trigger the onBeforeCompileHead event
		$app = \JFactory::getApplication();
		$app->triggerEvent('onBeforeCompileHead');

		// Get line endings
		$lnEnd        = $document->_getLineEnd();
		$tab          = $document->_getTab();
		$tagEnd       = ' />';
		$buffer       = '';
		$mediaVersion = $document->getMediaVersion();

		// Generate charset when using HTML5 (should happen first)
		if ($document->isHtml5())
		{
			$buffer .= $tab . '<meta charset="' .
$document->getCharset() . '" />' . $lnEnd;
		}

		// Generate base tag (need to happen early)
		$base = $document->getBase();

		if (!empty($base))
		{
			$buffer .= $tab . '<base href="' . $base .
'" />' . $lnEnd;
		}

		// Generate META tags (needs to happen as early as possible in the head)
		foreach ($document->_metaTags as $type => $tag)
		{
			foreach ($tag as $name => $content)
			{
				if ($type == 'http-equiv' &&
!($document->isHtml5() && $name == 'content-type'))
				{
					$buffer .= $tab . '<meta http-equiv="' . $name .
'" content="' . htmlspecialchars($content, ENT_COMPAT,
'UTF-8') . '" />' . $lnEnd;
				}
				elseif ($type != 'http-equiv' && !empty($content))
				{
					if (is_array($content))
					{
						foreach ($content as $value)
						{
							$buffer .= $tab . '<meta ' . $type .
'="' . $name . '" content="' .
htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '"
/>' . $lnEnd;
						}
					}
					else
					{
						$buffer .= $tab . '<meta ' . $type . '="'
. $name . '" content="' . htmlspecialchars($content,
ENT_COMPAT, 'UTF-8') . '" />' . $lnEnd;
					}
				}
			}
		}

		// Don't add empty descriptions
		$documentDescription = $document->getDescription();

		if ($documentDescription)
		{
			$buffer .= $tab . '<meta name="description"
content="' . htmlspecialchars($documentDescription, ENT_COMPAT,
'UTF-8') . '" />' . $lnEnd;
		}

		// Don't add empty generators
		$generator = $document->getGenerator();

		if ($generator)
		{
			$buffer .= $tab . '<meta name="generator"
content="' . htmlspecialchars($generator, ENT_COMPAT,
'UTF-8') . '" />' . $lnEnd;
		}

		$buffer .= $tab . '<title>' .
htmlspecialchars($document->getTitle(), ENT_COMPAT, 'UTF-8') .
'</title>' . $lnEnd;

		// Generate link declarations
		foreach ($document->_links as $link => $linkAtrr)
		{
			$buffer .= $tab . '<link href="' . $link .
'" ' . $linkAtrr['relType'] . '="'
. $linkAtrr['relation'] . '"';

			if (is_array($linkAtrr['attribs']))
			{
				if ($temp = ArrayHelper::toString($linkAtrr['attribs']))
				{
					$buffer .= ' ' . $temp;
				}
			}

			$buffer .= ' />' . $lnEnd;
		}

		$defaultCssMimes = array('text/css');

		// Generate stylesheet links
		foreach ($document->_styleSheets as $src => $attribs)
		{
			// Check if stylesheet uses IE conditional statements.
			$conditional = isset($attribs['options']) &&
isset($attribs['options']['conditional']) ?
$attribs['options']['conditional'] : null;

			// Check if script uses media version.
			if (isset($attribs['options']['version']) &&
$attribs['options']['version'] && strpos($src,
'?') === false
				&& ($mediaVersion ||
$attribs['options']['version'] !== 'auto'))
			{
				$src .= '?' .
($attribs['options']['version'] === 'auto' ?
$mediaVersion : $attribs['options']['version']);
			}

			$buffer .= $tab;

			// This is for IE conditional statements support.
			if (!is_null($conditional))
			{
				$buffer .= '<!--[if ' . $conditional . ']>';
			}

			$buffer .= '<link href="' . $src . '"
rel="stylesheet"';

			// Add script tag attributes.
			foreach ($attribs as $attrib => $value)
			{
				// Don't add the 'options' attribute. This attribute is
for internal use (version, conditional, etc).
				if ($attrib === 'options')
				{
					continue;
				}

				// Don't add type attribute if document is HTML5 and it's a
default mime type. 'mime' is for B/C.
				if (in_array($attrib, array('type', 'mime'))
&& $document->isHtml5() && in_array($value,
$defaultCssMimes))
				{
					continue;
				}

				// Don't add type attribute if document is HTML5 and it's a
default mime type. 'mime' is for B/C.
				if ($attrib === 'mime')
				{
					$attrib = 'type';
				}

				// Add attribute to script tag output.
				$buffer .= ' ' . htmlspecialchars($attrib, ENT_COMPAT,
'UTF-8');

				// Json encode value if it's an array.
				$value = !is_scalar($value) ? json_encode($value) : $value;

				$buffer .= '="' . htmlspecialchars($value, ENT_COMPAT,
'UTF-8') . '"';
			}

			$buffer .= $tagEnd;

			// This is for IE conditional statements support.
			if (!is_null($conditional))
			{
				$buffer .= '<![endif]-->';
			}

			$buffer .= $lnEnd;
		}

		// Generate stylesheet declarations
		foreach ($document->_style as $type => $content)
		{
			$buffer .= $tab . '<style';

			if (!is_null($type) && (!$document->isHtml5() ||
!in_array($type, $defaultCssMimes)))
			{
				$buffer .= ' type="' . $type . '"';
			}

			$buffer .= '>' . $lnEnd;

			// This is for full XHTML support.
			if ($document->_mime != 'text/html')
			{
				$buffer .= $tab . $tab . '/*<![CDATA[*/' . $lnEnd;
			}

			$buffer .= $content . $lnEnd;

			// See above note
			if ($document->_mime != 'text/html')
			{
				$buffer .= $tab . $tab . '/*]]>*/' . $lnEnd;
			}

			$buffer .= $tab . '</style>' . $lnEnd;
		}

		// Generate scripts options
		$scriptOptions = $document->getScriptOptions();

		if (!empty($scriptOptions))
		{
			$buffer .= $tab . '<script type="application/json"
class="joomla-script-options new">';

			$prettyPrint = (JDEBUG && defined('JSON_PRETTY_PRINT')
? JSON_PRETTY_PRINT : false);
			$jsonOptions = json_encode($scriptOptions, $prettyPrint);
			$jsonOptions = $jsonOptions ? $jsonOptions : '{}';

			$buffer .= $jsonOptions;
			$buffer .= '</script>' . $lnEnd;
		}

		$defaultJsMimes         = array('text/javascript',
'application/javascript', 'text/x-javascript',
'application/x-javascript');
		$html5NoValueAttributes = array('defer', 'async');

		// Generate script file links
		foreach ($document->_scripts as $src => $attribs)
		{
			// Check if script uses IE conditional statements.
			$conditional = isset($attribs['options']) &&
isset($attribs['options']['conditional']) ?
$attribs['options']['conditional'] : null;

			// Check if script uses media version.
			if (isset($attribs['options']['version']) &&
$attribs['options']['version'] && strpos($src,
'?') === false
				&& ($mediaVersion ||
$attribs['options']['version'] !== 'auto'))
			{
				$src .= '?' .
($attribs['options']['version'] === 'auto' ?
$mediaVersion : $attribs['options']['version']);
			}

			$buffer .= $tab;

			// This is for IE conditional statements support.
			if (!is_null($conditional))
			{
				$buffer .= '<!--[if ' . $conditional . ']>';
			}

			$buffer .= '<script src="' . $src .
'"';

			// Add script tag attributes.
			foreach ($attribs as $attrib => $value)
			{
				// Don't add the 'options' attribute. This attribute is
for internal use (version, conditional, etc).
				if ($attrib === 'options')
				{
					continue;
				}

				// Don't add type attribute if document is HTML5 and it's a
default mime type. 'mime' is for B/C.
				if (in_array($attrib, array('type', 'mime'))
&& $document->isHtml5() && in_array($value,
$defaultJsMimes))
				{
					continue;
				}

				// B/C: If defer and async is false or empty don't render the
attribute.
				if (in_array($attrib, array('defer', 'async'))
&& !$value)
				{
					continue;
				}

				// Don't add type attribute if document is HTML5 and it's a
default mime type. 'mime' is for B/C.
				if ($attrib === 'mime')
				{
					$attrib = 'type';
				}
				// B/C defer and async can be set to yes when using the old method.
				elseif (in_array($attrib, array('defer', 'async'))
&& $value === true)
				{
					$value = $attrib;
				}

				// Add attribute to script tag output.
				$buffer .= ' ' . htmlspecialchars($attrib, ENT_COMPAT,
'UTF-8');

				if (!($document->isHtml5() && in_array($attrib,
$html5NoValueAttributes)))
				{
					// Json encode value if it's an array.
					$value = !is_scalar($value) ? json_encode($value) : $value;

					$buffer .= '="' . htmlspecialchars($value, ENT_COMPAT,
'UTF-8') . '"';
				}
			}

			$buffer .= '></script>';

			// This is for IE conditional statements support.
			if (!is_null($conditional))
			{
				$buffer .= '<![endif]-->';
			}

			$buffer .= $lnEnd;
		}

		// Generate script declarations
		foreach ($document->_script as $type => $content)
		{
			$buffer .= $tab . '<script';

			if (!is_null($type) && (!$document->isHtml5() ||
!in_array($type, $defaultJsMimes)))
			{
				$buffer .= ' type="' . $type . '"';
			}

			$buffer .= '>' . $lnEnd;

			// This is for full XHTML support.
			if ($document->_mime != 'text/html')
			{
				$buffer .= $tab . $tab . '//<![CDATA[' . $lnEnd;
			}

			$buffer .= $content . $lnEnd;

			// See above note
			if ($document->_mime != 'text/html')
			{
				$buffer .= $tab . $tab . '//]]>' . $lnEnd;
			}

			$buffer .= $tab . '</script>' . $lnEnd;
		}

		// Output the custom tags - array_unique makes sure that we don't
output the same tags twice
		foreach (array_unique($document->_custom) as $custom)
		{
			$buffer .= $tab . $custom . $lnEnd;
		}

		return ltrim($buffer, $tab);
	}
}
Renderer/Html/MessageRenderer.php000064400000004113151157371000013001
0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document\Renderer\Html;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Document\DocumentRenderer;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Layout\LayoutHelper;

/**
 * HTML document renderer for the system message queue
 *
 * @since  3.5
 */
class MessageRenderer extends DocumentRenderer
{
	/**
	 * Renders the error stack and returns the results as a string
	 *
	 * @param   string  $name     Not used.
	 * @param   array   $params   Associative array of values
	 * @param   string  $content  Not used.
	 *
	 * @return  string  The output of the script
	 *
	 * @since   3.5
	 */
	public function render($name, $params = array(), $content = null)
	{
		$msgList     = $this->getData();
		$displayData = array(
			'msgList' => $msgList,
			'name'    => $name,
			'params'  => $params,
			'content' => $content,
		);

		$app        = \JFactory::getApplication();
		$chromePath = JPATH_THEMES . '/' . $app->getTemplate() .
'/html/message.php';

		if (file_exists($chromePath))
		{
			include_once $chromePath;
		}

		if (function_exists('renderMessage'))
		{
			Log::add('renderMessage() is deprecated. Override system message
rendering with layouts instead.', Log::WARNING,
'deprecated');

			return renderMessage($msgList);
		}

		return LayoutHelper::render('joomla.system.message',
$displayData);
	}

	/**
	 * Get and prepare system message data for output
	 *
	 * @return  array  An array contains system message
	 *
	 * @since   3.5
	 */
	private function getData()
	{
		// Initialise variables.
		$lists = array();

		// Get the message queue
		$messages = \JFactory::getApplication()->getMessageQueue();

		// Build the sorted message list
		if (is_array($messages) && !empty($messages))
		{
			foreach ($messages as $msg)
			{
				if (isset($msg['type']) &&
isset($msg['message']))
				{
					$lists[$msg['type']][] = $msg['message'];
				}
			}
		}

		return $lists;
	}
}
Renderer/Html/ModuleRenderer.php000064400000005255151157371000012652
0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document\Renderer\Html;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Document\DocumentRenderer;
use Joomla\CMS\Helper\ModuleHelper;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Layout\LayoutHelper;
use Joomla\Registry\Registry;

/**
 * HTML document renderer for a single module
 *
 * @since  3.5
 */
class ModuleRenderer extends DocumentRenderer
{
	/**
	 * Renders a module script and returns the results as a string
	 *
	 * @param   string  $module   The name of the module to render
	 * @param   array   $attribs  Associative array of values
	 * @param   string  $content  If present, module information from the
buffer will be used
	 *
	 * @return  string  The output of the script
	 *
	 * @since   3.5
	 */
	public function render($module, $attribs = array(), $content = null)
	{
		if (!is_object($module))
		{
			$title = isset($attribs['title']) ?
$attribs['title'] : null;

			$module = ModuleHelper::getModule($module, $title);

			if (!is_object($module))
			{
				if (is_null($content))
				{
					return '';
				}

				/**
				 * If module isn't found in the database but data has been pushed
in the buffer
				 * we want to render it
				 */
				$tmp = $module;
				$module = new \stdClass;
				$module->params = null;
				$module->module = $tmp;
				$module->id = 0;
				$module->user = 0;
			}
		}

		// Set the module content
		if (!is_null($content))
		{
			$module->content = $content;
		}

		// Get module parameters
		$params = new Registry($module->params);

		// Use parameters from template
		if (isset($attribs['params']))
		{
			$template_params = new
Registry(html_entity_decode($attribs['params'], ENT_COMPAT,
'UTF-8'));
			$params->merge($template_params);
			$module = clone $module;
			$module->params = (string) $params;
		}

		// Default for compatibility purposes. Set cachemode parameter or use
JModuleHelper::moduleCache from within the module instead
		$cachemode = $params->get('cachemode',
'oldstatic');

		if ($params->get('cache', 0) == 1 &&
\JFactory::getConfig()->get('caching') >= 1 &&
$cachemode != 'id' && $cachemode != 'safeuri')
		{
			// Default to itemid creating method and workarounds on
			$cacheparams = new \stdClass;
			$cacheparams->cachemode = $cachemode;
			$cacheparams->class = 'JModuleHelper';
			$cacheparams->method = 'renderModule';
			$cacheparams->methodparams = array($module, $attribs);

			return ModuleHelper::ModuleCache($module, $params, $cacheparams);
		}

		return ModuleHelper::renderModule($module, $attribs);
	}
}
Renderer/Html/ModulesRenderer.php000064400000003600151157371000013025
0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document\Renderer\Html;

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Document\DocumentRenderer;
use Joomla\CMS\Helper\ModuleHelper;
use Joomla\CMS\Layout\LayoutHelper;

/**
 * HTML document renderer for a module position
 *
 * @since  3.5
 */
class ModulesRenderer extends DocumentRenderer
{
	/**
	 * Renders multiple modules script and returns the results as a string
	 *
	 * @param   string  $position  The position of the modules to render
	 * @param   array   $params    Associative array of values
	 * @param   string  $content   Module content
	 *
	 * @return  string  The output of the script
	 *
	 * @since   3.5
	 */
	public function render($position, $params = array(), $content = null)
	{
		$renderer = $this->_doc->loadRenderer('module');
		$buffer   = '';

		$app          = \JFactory::getApplication();
		$user         = \JFactory::getUser();
		$frontediting = ($app->isClient('site') &&
$app->get('frontediting', 1) && !$user->guest);
		$menusEditing = ($app->get('frontediting', 1) == 2)
&& $user->authorise('core.edit',
'com_menus');

		foreach (ModuleHelper::getModules($position) as $mod)
		{
			$moduleHtml = $renderer->render($mod, $params, $content);

			if ($frontediting && trim($moduleHtml) != ''
&& $user->authorise('module.edit.frontend',
'com_modules.module.' . $mod->id))
			{
				$displayData = array('moduleHtml' => &$moduleHtml,
'module' => $mod, 'position' => $position,
'menusediting' => $menusEditing);
				LayoutHelper::render('joomla.edit.frontediting_modules',
$displayData);
			}

			$buffer .= $moduleHtml;
		}

		\JEventDispatcher::getInstance()->trigger('onAfterRenderModules',
array(&$buffer, &$params));

		return $buffer;
	}
}
XmlDocument.php000064400000004755151157371000007527 0ustar00<?php
/**
 * Joomla! Content Management System
 *
 * @copyright  Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license    GNU General Public License version 2 or later; see
LICENSE.txt
 */

namespace Joomla\CMS\Document;

defined('JPATH_PLATFORM') or die;

/**
 * XmlDocument class, provides an easy interface to parse and display XML
output
 *
 * @since  1.7.0
 */
class XmlDocument extends Document
{
	/**
	 * Document name
	 *
	 * @var    string
	 * @since  3.0.0
	 */
	protected $name = 'joomla';

	/**
	 * Flag indicating the document should be downloaded (Content-Disposition
= attachment) versus displayed inline
	 *
	 * @var    boolean
	 * @since  3.9.0
	 */
	protected $isDownload = false;

	/**
	 * Class constructor
	 *
	 * @param   array  $options  Associative array of options
	 *
	 * @since   1.7.0
	 */
	public function __construct($options = array())
	{
		parent::__construct($options);

		// Set mime type
		$this->_mime = 'application/xml';

		// Set document type
		$this->_type = 'xml';
	}

	/**
	 * Render the document.
	 *
	 * @param   boolean  $cache   If true, cache the output
	 * @param   array    $params  Associative array of attributes
	 *
	 * @return  string  The rendered data
	 *
	 * @since  1.7.0
	 */
	public function render($cache = false, $params = array())
	{
		parent::render($cache, $params);

		$disposition = $this->isDownload ? 'attachment' :
'inline';

		\JFactory::getApplication()->setHeader('Content-disposition',
$disposition . '; filename="' . $this->getName() .
'.xml"', true);

		return $this->getBuffer();
	}

	/**
	 * Returns the document name
	 *
	 * @return  string
	 *
	 * @since  1.7.0
	 */
	public function getName()
	{
		return $this->name;
	}

	/**
	 * Sets the document name
	 *
	 * @param   string  $name  Document name
	 *
	 * @return  XmlDocument instance of $this to allow chaining
	 *
	 * @since   1.7.0
	 */
	public function setName($name = 'joomla')
	{
		$this->name = $name;

		return $this;
	}

	/**
	 * Check if this document is intended for download
	 *
	 * @return  string
	 *
	 * @since   3.9.0
	 */
	public function isDownload()
	{
		return $this->isDownload;
	}

	/**
	 * Sets the document's download state
	 *
	 * @param   boolean  $download  If true, this document will be downloaded;
if false, this document will be displayed inline
	 *
	 * @return  XmlDocument instance of $this to allow chaining
	 *
	 * @since   3.9.0
	 */
	public function setDownload($download = false)
	{
		$this->isDownload = $download;

		return $this;
	}
}