first commit
This commit is contained in:
471
components/com_jce/editor/libraries/classes/application.php
Normal file
471
components/com_jce/editor/libraries/classes/application.php
Normal file
@@ -0,0 +1,471 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
require_once JPATH_ADMINISTRATOR . '/components/com_jce/includes/base.php';
|
||||
|
||||
/**
|
||||
* JCE class.
|
||||
*
|
||||
* @static
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
class WFApplication extends JObject
|
||||
{
|
||||
// Editor instance
|
||||
protected static $instance;
|
||||
|
||||
// Editor Profile
|
||||
protected static $profile = array();
|
||||
|
||||
// Editor Params
|
||||
protected static $params = array();
|
||||
|
||||
// JInput Reference
|
||||
public $input;
|
||||
|
||||
/**
|
||||
* Constructor activating the default information of the class.
|
||||
*/
|
||||
public function __construct($config = array())
|
||||
{
|
||||
$this->setProperties($config);
|
||||
|
||||
// store a reference to the Joomla Application input
|
||||
$this->input = JFactory::getApplication()->input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to a editor object.
|
||||
*
|
||||
* This method must be invoked as:
|
||||
* <pre> $browser =JContentEditor::getInstance();</pre>
|
||||
*
|
||||
* @return JCE The editor object
|
||||
*/
|
||||
public static function getInstance($config = array())
|
||||
{
|
||||
if (!isset(self::$instance)) {
|
||||
self::$instance = new self($config);
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current version.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getVersion()
|
||||
{
|
||||
$manifest = WF_ADMINISTRATOR . '/jce.xml';
|
||||
|
||||
$version = md5_file($manifest);
|
||||
|
||||
return $version;
|
||||
}
|
||||
|
||||
protected function getComponent($id = null, $option = null)
|
||||
{
|
||||
if ($id) {
|
||||
$components = JComponentHelper::getComponents();
|
||||
|
||||
foreach ($components as $option => $component) {
|
||||
if ($id == $component->id) {
|
||||
return $component;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return JComponentHelper::getComponent($option);
|
||||
}
|
||||
|
||||
public function getContext()
|
||||
{
|
||||
$option = JFactory::getApplication()->input->getCmd('option');
|
||||
$component = JComponentHelper::getComponent($option, true);
|
||||
|
||||
return $component->id;
|
||||
}
|
||||
|
||||
private function getProfileVars()
|
||||
{
|
||||
$app = JFactory::getApplication();
|
||||
$user = JFactory::getUser();
|
||||
$option = $this->getComponentOption();
|
||||
|
||||
$settings = array(
|
||||
'option' => $option,
|
||||
'area' => 2,
|
||||
'device' => 'desktop',
|
||||
'groups' => array(),
|
||||
);
|
||||
|
||||
// find the component if this is called from within the JCE component
|
||||
if ($option == 'com_jce') {
|
||||
$context = $app->input->getInt('context');
|
||||
|
||||
if ($context) {
|
||||
|
||||
if ($context === 'mediafield') {
|
||||
$settings['option'] = 'mediafield';
|
||||
} else {
|
||||
$component = $this->getComponent($context);
|
||||
$settings['option'] = $component->option;
|
||||
}
|
||||
}
|
||||
|
||||
$profile_id = $app->input->getInt('profile_id');
|
||||
|
||||
if ($profile_id) {
|
||||
$settings['profile_id'] = $profile_id;
|
||||
}
|
||||
}
|
||||
|
||||
// get the Joomla! area, default to "site"
|
||||
$settings['area'] = $app->getClientId() === 0 ? 1 : 2;
|
||||
|
||||
$mobile = new Wf_Mobile_Detect();
|
||||
|
||||
// phone
|
||||
if ($mobile->isMobile()) {
|
||||
$settings['device'] = 'phone';
|
||||
}
|
||||
|
||||
if ($mobile->isTablet()) {
|
||||
$settings['device'] = 'tablet';
|
||||
}
|
||||
|
||||
$settings['groups'] = $user->getAuthorisedGroups();
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
private function isCorePlugin($plugin)
|
||||
{
|
||||
return in_array($plugin, array('core', 'autolink', 'cleanup', 'code', 'format', 'importcss', 'colorpicker', 'upload', 'branding', 'inlinepopups', 'figure', 'ui'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an appropriate editor profile.
|
||||
*/
|
||||
public function getProfile($plugin = '', $id = 0)
|
||||
{
|
||||
// reset the value if it is a core plugin
|
||||
if ($this->isCorePlugin($plugin)) {
|
||||
$plugin = '';
|
||||
}
|
||||
|
||||
// get the profile variables for the current context
|
||||
$options = $this->getProfileVars();
|
||||
|
||||
// add plugin to options array
|
||||
$options['plugin'] = $plugin;
|
||||
|
||||
// assign profile_id to simple variable
|
||||
if (isset($options['profile_id'])) {
|
||||
$id = (int) $options['profile_id'];
|
||||
}
|
||||
|
||||
// create a signature to store
|
||||
$signature = md5(serialize($options));
|
||||
|
||||
if (!isset(self::$profile[$signature])) {
|
||||
$db = JFactory::getDBO();
|
||||
$user = JFactory::getUser();
|
||||
$app = JFactory::getApplication();
|
||||
|
||||
$query = $db->getQuery(true);
|
||||
$query->select('*')->from('#__wf_profiles')->where('published = 1')->order('ordering ASC');
|
||||
|
||||
if ($id) {
|
||||
$query->where('id = ' . (int) $id);
|
||||
}
|
||||
|
||||
$db->setQuery($query);
|
||||
$profiles = $db->loadObjectList();
|
||||
|
||||
// nothing found...
|
||||
if (empty($profiles)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// select and return a specific profile by id
|
||||
if ($id) {
|
||||
// return
|
||||
return (object) $profiles[0];
|
||||
}
|
||||
|
||||
foreach ($profiles as $item) {
|
||||
// at least one user group or user must be set
|
||||
if (empty($item->types) && empty($item->users)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check user groups - a value should always be set
|
||||
$groups = array_intersect($options['groups'], explode(',', $item->types));
|
||||
|
||||
// user not in the current group...
|
||||
if (empty($groups)) {
|
||||
// no additional users set or no user match
|
||||
if (empty($item->users) || in_array($user->id, explode(',', $item->users)) === false) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// check component
|
||||
if (!empty($item->components)) {
|
||||
if (in_array($options['option'], explode(',', $item->components)) === false) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// set device default as 'desktop,tablet,mobile'
|
||||
if (empty($item->device)) {
|
||||
$item->device = 'desktop,tablet,phone';
|
||||
}
|
||||
|
||||
// check device
|
||||
if (in_array($options['device'], explode(',', $item->device)) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check area
|
||||
if (!empty($item->area) && (int) $item->area != $options['area']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check against passed in plugin value
|
||||
if ($plugin && in_array($plugin, explode(',', $item->plugins)) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// decrypt params
|
||||
if (!empty($item->params)) {
|
||||
$item->params = JceEncryptHelper::decrypt($item->params);
|
||||
}
|
||||
|
||||
// assign item to profile
|
||||
self::$profile[$signature] = (object) $item;
|
||||
|
||||
// return
|
||||
return self::$profile[$signature];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return self::$profile[$signature];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the component option.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getComponentOption()
|
||||
{
|
||||
$app = JFactory::getApplication();
|
||||
|
||||
$option = $app->input->getCmd('option', '');
|
||||
|
||||
switch ($option) {
|
||||
case 'com_section':
|
||||
$option = 'com_content';
|
||||
break;
|
||||
case 'com_categories':
|
||||
$section = $app->input->getCmd('section');
|
||||
|
||||
if ($section) {
|
||||
$option = $section;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return $option;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get editor parameters.
|
||||
*
|
||||
* @param array $options
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function getParams($options = array())
|
||||
{
|
||||
$app = JFactory::getApplication();
|
||||
|
||||
if (!isset(self::$params)) {
|
||||
self::$params = array();
|
||||
}
|
||||
|
||||
// set blank key if not set
|
||||
if (!isset($options['key'])) {
|
||||
$options['key'] = '';
|
||||
}
|
||||
// set blank path if not set
|
||||
if (!isset($options['path'])) {
|
||||
$options['path'] = '';
|
||||
}
|
||||
|
||||
// get plugin name
|
||||
$plugin = $app->input->getCmd('plugin', '');
|
||||
|
||||
// reset the plugin value if this is not called from within the JCE component
|
||||
if ($app->input->getCmd('option') !== 'com_jce') {
|
||||
$plugin = '';
|
||||
}
|
||||
|
||||
if ($plugin) {
|
||||
// optional caller, eg: Link
|
||||
$caller = '';
|
||||
|
||||
// get name and caller from plugin name
|
||||
if (strpos($plugin, '.') !== false) {
|
||||
list($plugin, $caller) = explode('.', $plugin);
|
||||
|
||||
if ($caller) {
|
||||
$options['caller'] = $caller;
|
||||
}
|
||||
}
|
||||
|
||||
$options['plugin'] = $plugin;
|
||||
}
|
||||
|
||||
$signature = serialize($options);
|
||||
|
||||
if (empty(self::$params[$signature])) {
|
||||
// get plugin
|
||||
$editor = JPluginHelper::getPlugin('editors', 'jce');
|
||||
|
||||
if (empty($editor->params)) {
|
||||
$editor->params = '{}';
|
||||
}
|
||||
|
||||
// get editor params as an associative array
|
||||
$data1 = json_decode($editor->params, true);
|
||||
|
||||
// if null or false, revert to array
|
||||
if (empty($data1)) {
|
||||
$data1 = array();
|
||||
}
|
||||
|
||||
// assign params to "editor" key
|
||||
$data1 = array('editor' => $data1);
|
||||
|
||||
// get params data for this profile
|
||||
$profile = $this->getProfile($plugin);
|
||||
|
||||
// create empty default if no profile or params are set
|
||||
$params = empty($profile->params) ? '{}' : $profile->params;
|
||||
|
||||
// get profile params as an associative array
|
||||
$data2 = json_decode($params, true);
|
||||
|
||||
// if null or false, revert to array
|
||||
if (empty($data2)) {
|
||||
$data2 = array();
|
||||
}
|
||||
|
||||
// merge params, but ignore empty values
|
||||
$data = WFUtility::array_merge_recursive_distinct($data1, $data2, true);
|
||||
|
||||
// create new registry with params
|
||||
$params = new JRegistry($data);
|
||||
|
||||
self::$params[$signature] = $params;
|
||||
}
|
||||
|
||||
return self::$params[$signature];
|
||||
}
|
||||
|
||||
private function isEmptyValue($value)
|
||||
{
|
||||
if (is_null($value)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
return empty($value);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a parameter by key.
|
||||
*
|
||||
* @param $key Parameter key eg: editor.width
|
||||
* @param $fallback Fallback value
|
||||
* @param $default Default value
|
||||
*/
|
||||
public function getParam($key, $fallback = '', $default = '', $type = 'string')
|
||||
{
|
||||
// get params for base key
|
||||
$params = $this->getParams();
|
||||
|
||||
// get a parameter
|
||||
$value = $params->get($key);
|
||||
|
||||
// key not present in params or was empty string or empty array (JRegistry returns null), use fallback value
|
||||
if (self::isEmptyValue($value)) {
|
||||
// set default as empty string
|
||||
$value = '';
|
||||
|
||||
// key does not exist (parameter was not set) - use fallback
|
||||
if ($params->exists($key) === false) {
|
||||
$value = $fallback;
|
||||
|
||||
// if fallback is empty, revert to system default if it is non-empty
|
||||
if ($fallback == '' && $default != '') {
|
||||
$value = $default;
|
||||
|
||||
// reset $default to prevent clearing
|
||||
$default = '';
|
||||
}
|
||||
// parameter is set, but is empty, but fallback is not (inherited values)
|
||||
} else if ($fallback != '') {
|
||||
$value = $fallback;
|
||||
}
|
||||
}
|
||||
|
||||
// clean string value of whitespace
|
||||
if (is_string($value)) {
|
||||
$value = trim(preg_replace('#[\n\r\t]+#', '', $value));
|
||||
}
|
||||
|
||||
// cast default to float if numeric
|
||||
if (is_numeric($default)) {
|
||||
$default = (float) $default;
|
||||
}
|
||||
|
||||
// cast value to float if numeric
|
||||
if (is_numeric($value)) {
|
||||
$value = (float) $value;
|
||||
}
|
||||
|
||||
// if value is equal to system default, clear $value and return
|
||||
if ($value === $default) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// cast value to boolean
|
||||
if ($type == 'boolean') {
|
||||
$value = (bool) $value;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
1815
components/com_jce/editor/libraries/classes/browser.php
Normal file
1815
components/com_jce/editor/libraries/classes/browser.php
Normal file
File diff suppressed because it is too large
Load Diff
697
components/com_jce/editor/libraries/classes/document.php
Normal file
697
components/com_jce/editor/libraries/classes/document.php
Normal file
@@ -0,0 +1,697 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
class WFDocument extends JObject
|
||||
{
|
||||
/**
|
||||
* Array of linked scripts.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $scripts = array();
|
||||
|
||||
/**
|
||||
* Array of scripts placed in the header.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $script = array();
|
||||
|
||||
/**
|
||||
* Array of linked style sheets.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $styles = array();
|
||||
|
||||
/**
|
||||
* Array of head items.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $head = array();
|
||||
|
||||
/**
|
||||
* Body content.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $body = '';
|
||||
|
||||
/**
|
||||
* Document title.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $title = '';
|
||||
|
||||
/**
|
||||
* Contains the document language setting.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $language = 'en-gb';
|
||||
|
||||
/**
|
||||
* Contains the document direction setting.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $direction = 'ltr';
|
||||
|
||||
private static $queryMap = array(
|
||||
'imgmanager'=> 'image',
|
||||
'imgmanager_ext' => 'imagepro'
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructor activating the default information of the class.
|
||||
*/
|
||||
public function __construct($config = array())
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// set document title
|
||||
if (isset($config['title'])) {
|
||||
$this->setTitle($config['title']);
|
||||
}
|
||||
|
||||
$this->setProperties($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to a WFDocument object.
|
||||
*
|
||||
* This method must be invoked as:
|
||||
* <pre> $document = WFDocument::getInstance();</pre>
|
||||
*
|
||||
* @return object WFDocument
|
||||
*/
|
||||
public static function getInstance($config = array())
|
||||
{
|
||||
static $instance;
|
||||
|
||||
if (!is_object($instance)) {
|
||||
$instance = new self($config);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the document title.
|
||||
*
|
||||
* @param string $title
|
||||
*/
|
||||
public function setTitle($title)
|
||||
{
|
||||
$this->title = $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the document title.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the document name.
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the document name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the editor URL.
|
||||
*
|
||||
* @param bool $relative
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getURL($relative = false)
|
||||
{
|
||||
if ($relative) {
|
||||
return JURI::root(true) . '/components/com_jce/editor';
|
||||
}
|
||||
|
||||
return JURI::root() . 'components/com_jce/editor';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the global document language declaration. Default is English (en-gb).
|
||||
*
|
||||
* @param string $lang
|
||||
*/
|
||||
public function setLanguage($lang = 'en-gb')
|
||||
{
|
||||
$this->language = strtolower($lang);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the document language.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLanguage()
|
||||
{
|
||||
return $this->language;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the global document direction declaration. Default is left-to-right (ltr).
|
||||
*
|
||||
* @param string $lang
|
||||
*/
|
||||
public function setDirection($dir = 'ltr')
|
||||
{
|
||||
$this->direction = strtolower($dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the document language.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDirection()
|
||||
{
|
||||
return $this->direction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a JCE resource url.
|
||||
*
|
||||
* @param string The path to resolve eg: libaries
|
||||
* @param bool Create a relative url
|
||||
*
|
||||
* @return full url
|
||||
*/
|
||||
private function getBaseURL($path, $type = '')
|
||||
{
|
||||
static $url;
|
||||
|
||||
if (!isset($url)) {
|
||||
$url = array();
|
||||
}
|
||||
|
||||
$signature = serialize(array($type, $path));
|
||||
|
||||
// Check if value is already stored
|
||||
if (!isset($url[$signature])) {
|
||||
// get the plugin name using this document instance
|
||||
$plugin = $this->get('name');
|
||||
|
||||
$base = $this->getURL(true) . '/';
|
||||
|
||||
$parts = explode('.', $path);
|
||||
$path = array_shift($parts);
|
||||
|
||||
switch ($path) {
|
||||
// JCE root folder
|
||||
case 'jce':
|
||||
$pre = $base . '';
|
||||
break;
|
||||
// JCE libraries resource folder
|
||||
case 'libraries':
|
||||
$pre = $base . 'libraries/' . $type;
|
||||
break;
|
||||
case 'pro':
|
||||
$pre = $base . 'libraries/pro/' . $type;
|
||||
break;
|
||||
case 'jquery':
|
||||
$pre = $base . 'libraries/vendor/jquery/' . $type;
|
||||
break;
|
||||
// TinyMCE folder
|
||||
case 'tiny_mce':
|
||||
$pre = $base . 'tiny_mce';
|
||||
break;
|
||||
// Tinymce plugins folder
|
||||
case 'plugins':
|
||||
$pre = $base . 'tiny_mce/plugins/' . $plugin . '/' . $type;
|
||||
break;
|
||||
// Extensions folder
|
||||
case 'extensions':
|
||||
$pre = $base . 'extensions';
|
||||
break;
|
||||
case 'joomla':
|
||||
return JURI::root(true);
|
||||
break;
|
||||
case 'media':
|
||||
return JURI::root(true) . '/media/system';
|
||||
break;
|
||||
case 'component':
|
||||
$pre = JURI::root(true) . '/administrator/components/com_jce/media/' . $type;
|
||||
break;
|
||||
default:
|
||||
$pre = $base . $path;
|
||||
break;
|
||||
}
|
||||
|
||||
if (count($parts)) {
|
||||
$pre = rtrim($pre, '/') . '/' . implode('/', $parts);
|
||||
}
|
||||
|
||||
// Store url
|
||||
$url[$signature] = $pre;
|
||||
}
|
||||
|
||||
return $url[$signature];
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a url to path.
|
||||
*
|
||||
* @param string $url
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function urlToPath($url)
|
||||
{
|
||||
jimport('joomla.filesystem.path');
|
||||
|
||||
$root = JURI::root(true);
|
||||
|
||||
// remove root from url
|
||||
if (!empty($root)) {
|
||||
$url = substr($url, strlen($root));
|
||||
}
|
||||
|
||||
return WFUtility::makePath(JPATH_SITE, JPath::clean($url));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an image url.
|
||||
*
|
||||
* @param string The file to load including path and extension eg: libaries.image.gif
|
||||
*
|
||||
* @return Image url
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public function image($image, $root = 'libraries')
|
||||
{
|
||||
$parts = explode('.', $image);
|
||||
$parts = preg_replace('#[^A-Z0-9-_]#i', '', $parts);
|
||||
|
||||
$ext = array_pop($parts);
|
||||
$name = trim(array_pop($parts), '/');
|
||||
|
||||
$parts[] = 'img';
|
||||
$parts[] = $name . '.' . $ext;
|
||||
|
||||
return $this->getBaseURL($root) . implode('/', $parts);
|
||||
}
|
||||
|
||||
public function removeScript($file, $root = 'libraries')
|
||||
{
|
||||
$file = $this->buildScriptPath($file, $root);
|
||||
unset($this->scripts[$file]);
|
||||
}
|
||||
|
||||
public function removeCss($file, $root = 'libraries')
|
||||
{
|
||||
$file = $this->buildStylePath($file, $root);
|
||||
unset($this->styles[$file]);
|
||||
}
|
||||
|
||||
public function buildScriptPath($file, $root)
|
||||
{
|
||||
$file = preg_replace('#[^A-Z0-9-_\/\.]#i', '', $file);
|
||||
// get base dir
|
||||
$base = dirname($file);
|
||||
// remove extension if present
|
||||
$file = basename($file, '.js');
|
||||
// strip . and trailing /
|
||||
$file = trim(trim($base, '.'), '/') . '/' . $file . '.js';
|
||||
// remove leading and trailing slashes
|
||||
$file = trim($file, '/');
|
||||
// create path
|
||||
$file = $this->getBaseURL($root, 'js') . '/' . $file;
|
||||
// remove duplicate slashes
|
||||
$file = preg_replace('#[/\\\\]+#', '/', $file);
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
public function buildStylePath($file, $root)
|
||||
{
|
||||
$file = preg_replace('#[^A-Z0-9-_\/\.]#i', '', $file);
|
||||
// get base dir
|
||||
$base = dirname($file);
|
||||
// remove extension if present
|
||||
$file = basename($file, '.css');
|
||||
// strip . and trailing /
|
||||
$file = trim(trim($base, '.'), '/') . '/' . $file . '.css';
|
||||
// remove leading and trailing slashes
|
||||
$file = trim($file, '/');
|
||||
// create path
|
||||
$file = $this->getBaseURL($root, 'css') . '/' . $file;
|
||||
// remove duplicate slashes
|
||||
$file = preg_replace('#[/\\\\]+#', '/', $file);
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a javascript file.
|
||||
*
|
||||
* @param string The file to load including path eg: libaries.manager
|
||||
* @param bool Debug mode load src file
|
||||
*
|
||||
* @return echo script html
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public function addScript($files, $root = 'libraries', $type = 'text/javascript')
|
||||
{
|
||||
$files = (array) $files;
|
||||
|
||||
foreach ($files as $file) {
|
||||
// external link
|
||||
if (strpos($file, '://') !== false || strpos($file, 'index.php?option=com_jce') !== false) {
|
||||
$this->scripts[$file] = $type;
|
||||
} else {
|
||||
$file = $this->buildScriptPath($file, $root);
|
||||
// store path
|
||||
$this->scripts[$file] = $type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a css file.
|
||||
*
|
||||
* @param string The file to load including path eg: libaries.manager
|
||||
* @param string Root folder
|
||||
*
|
||||
* @return echo css html
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public function addStyleSheet($files, $root = 'libraries', $type = 'text/css')
|
||||
{
|
||||
$files = (array) $files;
|
||||
|
||||
foreach ($files as $file) {
|
||||
$url = $this->buildStylePath($file, $root);
|
||||
// store path
|
||||
$this->styles[$url] = $type;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
private function getScriptDeclarations()
|
||||
{
|
||||
return $this->script;
|
||||
}
|
||||
|
||||
private function getScripts()
|
||||
{
|
||||
return $this->scripts;
|
||||
}
|
||||
|
||||
private function getStyleSheets()
|
||||
{
|
||||
return $this->styles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup head data.
|
||||
*/
|
||||
private function setHead($data)
|
||||
{
|
||||
if (is_array($data)) {
|
||||
$this->head = array_merge($this->head, $data);
|
||||
} else {
|
||||
$this->head[] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
public function getQueryString($query = array())
|
||||
{
|
||||
$app = JFactory::getApplication();
|
||||
|
||||
// get plugin name and assign to query
|
||||
$name = $this->get('name');
|
||||
|
||||
// re-map plugin name
|
||||
if (array_key_exists($name, self::$queryMap)) {
|
||||
$name = self::$queryMap[$name];
|
||||
}
|
||||
|
||||
$query['plugin'] = $name;
|
||||
|
||||
// set slot
|
||||
$query['slot'] = $app->input->getCmd('slot');
|
||||
|
||||
// set standalone mode (for File Browser etc)
|
||||
$query['standalone'] = $this->get('standalone');
|
||||
|
||||
// set context id
|
||||
$query['context'] = $app->input->getInt('context');
|
||||
|
||||
// get token
|
||||
$token = JSession::getFormToken();
|
||||
|
||||
// set token
|
||||
$query[$token] = 1;
|
||||
|
||||
$output = array();
|
||||
|
||||
foreach ($query as $key => $value) {
|
||||
if ($value) {
|
||||
$output[] = $key . '=' . $value;
|
||||
}
|
||||
}
|
||||
|
||||
return implode('&', $output);
|
||||
}
|
||||
|
||||
private function getHash($files)
|
||||
{
|
||||
$seed = '';
|
||||
$hash = '';
|
||||
|
||||
// cast as array
|
||||
$files = (array) $files;
|
||||
|
||||
foreach ($files as $file) {
|
||||
|
||||
// only add stamp to static stylesheets
|
||||
if (strpos($file, '://') === false && strpos($file, 'index.php?option=com_jce') === false) {
|
||||
$seed .= basename($file);
|
||||
}
|
||||
}
|
||||
|
||||
if ($seed) {
|
||||
$hash = md5(WF_VERSION . $seed);
|
||||
}
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render document head data.
|
||||
*/
|
||||
private function getHead()
|
||||
{
|
||||
// set title
|
||||
$output = '<title>' . $this->getTitle() . '</title>' . "\n";
|
||||
|
||||
// render stylesheets
|
||||
if ($this->get('compress_css', 0)) {
|
||||
$file = JURI::base(true) . '/index.php?option=com_jce&' . $this->getQueryString(array('task' => 'plugin.pack', 'type' => 'css'));
|
||||
// add hash
|
||||
$file .= '&' . $this->getHash(array_keys($this->styles));
|
||||
|
||||
$output .= "\t\t<link href=\"" . $file . "\" rel=\"stylesheet\" type=\"text/css\" />\n";
|
||||
} else {
|
||||
foreach ($this->styles as $src => $type) {
|
||||
$hash = $this->getHash($src);
|
||||
|
||||
// only add stamp to static stylesheets
|
||||
if (!empty($hash)) {
|
||||
$hash = strpos($src, '?') === false ? '?' . $hash : '&' . $hash;
|
||||
}
|
||||
|
||||
$output .= "\t\t<link href=\"" . $src . $hash . '" rel="stylesheet" type="' . $type . "\" />\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Render scripts
|
||||
if ($this->get('compress_javascript', 0)) {
|
||||
$script = JURI::base(true) . '/index.php?option=com_jce&' . $this->getQueryString(array('task' => 'plugin.pack'));
|
||||
// add hash
|
||||
$script .= '&' . $this->getHash(array_keys($this->scripts));
|
||||
|
||||
$output .= "\t\t<script data-cfasync=\"false\" type=\"text/javascript\" src=\"" . $script . "\"></script>\n";
|
||||
} else {
|
||||
foreach ($this->scripts as $src => $type) {
|
||||
$hash = $this->getHash($src);
|
||||
|
||||
// only add stamp to static stylesheets
|
||||
if (!empty($hash)) {
|
||||
$hash = strpos($src, '?') === false ? '?' . $hash : '&' . $hash;
|
||||
}
|
||||
|
||||
$output .= "\t\t<script data-cfasync=\"false\" type=\"" . $type . '" src="' . $src . $hash . "\"></script>\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Script declarations
|
||||
foreach ($this->script as $type => $content) {
|
||||
$output .= "\t\t<script data-cfasync=\"false\" type=\"" . $type . '">' . $content . '</script>';
|
||||
}
|
||||
|
||||
// Other head data
|
||||
foreach ($this->head as $head) {
|
||||
$output .= "\t" . $head . "\n";
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
public function setBody($data = '')
|
||||
{
|
||||
$this->body = $data;
|
||||
}
|
||||
|
||||
private function getBody()
|
||||
{
|
||||
return $this->body;
|
||||
}
|
||||
|
||||
private function loadData()
|
||||
{
|
||||
//get the file content
|
||||
ob_start();
|
||||
require_once WF_EDITOR_LIBRARIES . '/views/plugin/index.php';
|
||||
$data = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the document.
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
// assign language
|
||||
$this->language = $this->getLanguage();
|
||||
$this->direction = $this->getDirection();
|
||||
|
||||
// load template data
|
||||
$output = $this->loadData();
|
||||
$output = $this->parseData($output);
|
||||
|
||||
exit($output);
|
||||
}
|
||||
|
||||
private function parseData($data)
|
||||
{
|
||||
$data = preg_replace_callback('#<!-- \[head\] -->#', array($this, 'getHead'), $data);
|
||||
$data = preg_replace_callback('#<!-- \[body\] -->#', array($this, 'getBody'), $data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* pack function for plugins.
|
||||
*/
|
||||
public function pack($minify = true, $gzip = false)
|
||||
{
|
||||
$app = JFactory::getApplication();
|
||||
|
||||
if ($app->input->getCmd('task') == 'pack') {
|
||||
|
||||
// check token
|
||||
JSession::checkToken('get') or jexit();
|
||||
|
||||
$type = $app->input->getWord('type', 'javascript');
|
||||
|
||||
// create packer
|
||||
$packer = new WFPacker(array('type' => $type));
|
||||
|
||||
$files = array();
|
||||
|
||||
switch ($type) {
|
||||
case 'javascript':
|
||||
$data = '';
|
||||
|
||||
foreach ($this->getScripts() as $src => $type) {
|
||||
if (strpos($src, '://') === false && strpos($src, 'index.php') === false) {
|
||||
$src .= preg_match('/\.js$/', $src) ? '' : '.js';
|
||||
|
||||
$files[] = $this->urlToPath($src);
|
||||
}
|
||||
}
|
||||
|
||||
// parse ini language files
|
||||
$parser = new WFLanguageParser(array(
|
||||
'plugins' => array('core' => array($this->getName()), 'external' => array()),
|
||||
'sections' => array('dlg', $this->getName() . '_dlg'),
|
||||
'mode' => 'plugin',
|
||||
'language' => WFLanguage::getTag()
|
||||
));
|
||||
|
||||
$data .= $parser->load();
|
||||
|
||||
// add script declarations
|
||||
/*foreach ($this->getScriptDeclarations() as $script) {
|
||||
$data .= $script;
|
||||
}*/
|
||||
|
||||
$packer->setContentEnd($data);
|
||||
|
||||
break;
|
||||
case 'css':
|
||||
foreach ($this->getStyleSheets() as $style => $type) {
|
||||
if (strpos($style, '://') === false && strpos($style, 'index.php') === false) {
|
||||
$style .= preg_match('/\.css$/', $style) ? '' : '.css';
|
||||
|
||||
$files[] = $this->urlToPath($style);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$packer->setFiles($files);
|
||||
$packer->pack($minify, $gzip);
|
||||
}
|
||||
}
|
||||
}
|
||||
1562
components/com_jce/editor/libraries/classes/editor.php
Normal file
1562
components/com_jce/editor/libraries/classes/editor.php
Normal file
File diff suppressed because it is too large
Load Diff
548
components/com_jce/editor/libraries/classes/encrypt.php
Normal file
548
components/com_jce/editor/libraries/classes/encrypt.php
Normal file
@@ -0,0 +1,548 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c)2009-2013 Nicholas K. Dionysopoulos
|
||||
* @license GNU General Public License version 3, or later
|
||||
*
|
||||
* @since 2.4
|
||||
*/
|
||||
|
||||
// Protection against direct access
|
||||
defined('JPATH_PLATFORM') or die();
|
||||
|
||||
/**
|
||||
* AES implementation in PHP (c) Chris Veness 2005-2013.
|
||||
* Right to use and adapt is granted for under a simple creative commons attribution
|
||||
* licence. No warranty of any form is offered.
|
||||
*
|
||||
* Modified for Akeeba Backup by Nicholas K. Dionysopoulos
|
||||
* Included for JCE with the kind permission of Nicholas K. Dionysopoulos
|
||||
*/
|
||||
class WFUtilEncrypt
|
||||
{
|
||||
// Sbox is pre-computed multiplicative inverse in GF(2^8) used in SubBytes and KeyExpansion [<5B>5.1.1]
|
||||
protected static $Sbox =
|
||||
array(0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||||
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
|
||||
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
|
||||
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
|
||||
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
|
||||
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
|
||||
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
|
||||
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
|
||||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, );
|
||||
|
||||
// Rcon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [<5B>5.2]
|
||||
protected static $Rcon = array(
|
||||
array(0x00, 0x00, 0x00, 0x00),
|
||||
array(0x01, 0x00, 0x00, 0x00),
|
||||
array(0x02, 0x00, 0x00, 0x00),
|
||||
array(0x04, 0x00, 0x00, 0x00),
|
||||
array(0x08, 0x00, 0x00, 0x00),
|
||||
array(0x10, 0x00, 0x00, 0x00),
|
||||
array(0x20, 0x00, 0x00, 0x00),
|
||||
array(0x40, 0x00, 0x00, 0x00),
|
||||
array(0x80, 0x00, 0x00, 0x00),
|
||||
array(0x1b, 0x00, 0x00, 0x00),
|
||||
array(0x36, 0x00, 0x00, 0x00), );
|
||||
|
||||
protected static $passwords = array();
|
||||
|
||||
/**
|
||||
* AES Cipher function: encrypt 'input' with Rijndael algorithm.
|
||||
*
|
||||
* @param input message as byte-array (16 bytes)
|
||||
* @param w key schedule as 2D byte-array (Nr+1 x Nb bytes) -
|
||||
* generated from the cipher key by KeyExpansion()
|
||||
*
|
||||
* @return ciphertext as byte-array (16 bytes)
|
||||
*/
|
||||
public static function Cipher($input, $w)
|
||||
{ // main Cipher function [<5B>5.1]
|
||||
$Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
|
||||
$Nr = count($w) / $Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys
|
||||
|
||||
$state = array(); // initialise 4xNb byte-array 'state' with input [<5B>3.4]
|
||||
for ($i = 0; $i < 4 * $Nb; ++$i) {
|
||||
$state[$i % 4][floor($i / 4)] = $input[$i];
|
||||
}
|
||||
|
||||
$state = self::AddRoundKey($state, $w, 0, $Nb);
|
||||
|
||||
for ($round = 1; $round < $Nr; ++$round) { // apply Nr rounds
|
||||
$state = self::SubBytes($state, $Nb);
|
||||
$state = self::ShiftRows($state, $Nb);
|
||||
$state = self::MixColumns($state, $Nb);
|
||||
$state = self::AddRoundKey($state, $w, $round, $Nb);
|
||||
}
|
||||
|
||||
$state = self::SubBytes($state, $Nb);
|
||||
$state = self::ShiftRows($state, $Nb);
|
||||
$state = self::AddRoundKey($state, $w, $Nr, $Nb);
|
||||
|
||||
$output = array(4 * $Nb); // convert state to 1-d array before returning [<5B>3.4]
|
||||
for ($i = 0; $i < 4 * $Nb; ++$i) {
|
||||
$output[$i] = $state[$i % 4][floor($i / 4)];
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
protected static function AddRoundKey($state, $w, $rnd, $Nb)
|
||||
{ // xor Round Key into state S [<5B>5.1.4]
|
||||
for ($r = 0; $r < 4; ++$r) {
|
||||
for ($c = 0; $c < $Nb; ++$c) {
|
||||
$state[$r][$c] ^= $w[$rnd * 4 + $c][$r];
|
||||
}
|
||||
}
|
||||
|
||||
return $state;
|
||||
}
|
||||
|
||||
protected static function SubBytes($s, $Nb)
|
||||
{ // apply SBox to state S [<5B>5.1.1]
|
||||
for ($r = 0; $r < 4; ++$r) {
|
||||
for ($c = 0; $c < $Nb; ++$c) {
|
||||
$s[$r][$c] = self::$Sbox[$s[$r][$c]];
|
||||
}
|
||||
}
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
protected static function ShiftRows($s, $Nb)
|
||||
{ // shift row r of state S left by r bytes [<5B>5.1.2]
|
||||
$t = array(4);
|
||||
for ($r = 1; $r < 4; ++$r) {
|
||||
for ($c = 0; $c < 4; ++$c) {
|
||||
$t[$c] = $s[$r][($c + $r) % $Nb];
|
||||
} // shift into temp copy
|
||||
for ($c = 0; $c < 4; ++$c) {
|
||||
$s[$r][$c] = $t[$c];
|
||||
} // and copy back
|
||||
} // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):
|
||||
return $s; // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf
|
||||
}
|
||||
|
||||
protected static function MixColumns($s, $Nb)
|
||||
{ // combine bytes of each col of state S [<5B>5.1.3]
|
||||
for ($c = 0; $c < 4; ++$c) {
|
||||
$a = array(4); // 'a' is a copy of the current column from 's'
|
||||
$b = array(4); // 'b' is a<>{02} in GF(2^8)
|
||||
for ($i = 0; $i < 4; ++$i) {
|
||||
$a[$i] = $s[$i][$c];
|
||||
$b[$i] = $s[$i][$c] & 0x80 ? $s[$i][$c] << 1 ^ 0x011b : $s[$i][$c] << 1;
|
||||
}
|
||||
// a[n] ^ b[n] is a<>{03} in GF(2^8)
|
||||
$s[0][$c] = $b[0] ^ $a[1] ^ $b[1] ^ $a[2] ^ $a[3]; // 2*a0 + 3*a1 + a2 + a3
|
||||
$s[1][$c] = $a[0] ^ $b[1] ^ $a[2] ^ $b[2] ^ $a[3]; // a0 * 2*a1 + 3*a2 + a3
|
||||
$s[2][$c] = $a[0] ^ $a[1] ^ $b[2] ^ $a[3] ^ $b[3]; // a0 + a1 + 2*a2 + 3*a3
|
||||
$s[3][$c] = $a[0] ^ $b[0] ^ $a[1] ^ $a[2] ^ $b[3]; // 3*a0 + a1 + a2 + 2*a3
|
||||
}
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
/**
|
||||
* Key expansion for Rijndael Cipher(): performs key expansion on cipher key
|
||||
* to generate a key schedule.
|
||||
*
|
||||
* @param key cipher key byte-array (16 bytes)
|
||||
*
|
||||
* @return key schedule as 2D byte-array (Nr+1 x Nb bytes)
|
||||
*/
|
||||
public static function KeyExpansion($key)
|
||||
{ // generate Key Schedule from Cipher Key [<5B>5.2]
|
||||
$Nb = 4; // block size (in words): no of columns in state (fixed at 4 for AES)
|
||||
$Nk = count($key) / 4; // key length (in words): 4/6/8 for 128/192/256-bit keys
|
||||
$Nr = $Nk + 6; // no of rounds: 10/12/14 for 128/192/256-bit keys
|
||||
|
||||
$w = array();
|
||||
$temp = array();
|
||||
|
||||
for ($i = 0; $i < $Nk; ++$i) {
|
||||
$r = array($key[4 * $i], $key[4 * $i + 1], $key[4 * $i + 2], $key[4 * $i + 3]);
|
||||
$w[$i] = $r;
|
||||
}
|
||||
|
||||
for ($i = $Nk; $i < ($Nb * ($Nr + 1)); ++$i) {
|
||||
$w[$i] = array();
|
||||
for ($t = 0; $t < 4; ++$t) {
|
||||
$temp[$t] = $w[$i - 1][$t];
|
||||
}
|
||||
if ($i % $Nk == 0) {
|
||||
$temp = self::SubWord(self::RotWord($temp));
|
||||
for ($t = 0; $t < 4; ++$t) {
|
||||
$temp[$t] ^= self::$Rcon[$i / $Nk][$t];
|
||||
}
|
||||
} elseif ($Nk > 6 && $i % $Nk == 4) {
|
||||
$temp = self::SubWord($temp);
|
||||
}
|
||||
for ($t = 0; $t < 4; ++$t) {
|
||||
$w[$i][$t] = $w[$i - $Nk][$t] ^ $temp[$t];
|
||||
}
|
||||
}
|
||||
|
||||
return $w;
|
||||
}
|
||||
|
||||
protected static function SubWord($w)
|
||||
{ // apply SBox to 4-byte word w
|
||||
for ($i = 0; $i < 4; ++$i) {
|
||||
$w[$i] = self::$Sbox[$w[$i]];
|
||||
}
|
||||
|
||||
return $w;
|
||||
}
|
||||
|
||||
protected static function RotWord($w)
|
||||
{ // rotate 4-byte word w left by one byte
|
||||
$tmp = $w[0];
|
||||
for ($i = 0; $i < 3; ++$i) {
|
||||
$w[$i] = $w[$i + 1];
|
||||
}
|
||||
$w[3] = $tmp;
|
||||
|
||||
return $w;
|
||||
}
|
||||
|
||||
/*
|
||||
* Unsigned right shift function, since PHP has neither >>> operator nor unsigned ints
|
||||
*
|
||||
* @param a number to be shifted (32-bit integer)
|
||||
* @param b number of bits to shift a to the right (0..31)
|
||||
* @return a right-shifted and zero-filled by b bits
|
||||
*/
|
||||
protected static function urs($a, $b)
|
||||
{
|
||||
$a &= 0xffffffff;
|
||||
$b &= 0x1f; // (bounds check)
|
||||
if ($a & 0x80000000 && $b > 0) { // if left-most bit set
|
||||
$a = ($a >> 1) & 0x7fffffff; // right-shift one bit & clear left-most bit
|
||||
$a = $a >> ($b - 1); // remaining right-shifts
|
||||
} else { // otherwise
|
||||
$a = ($a >> $b); // use normal right-shift
|
||||
}
|
||||
|
||||
return $a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt a text using AES encryption in Counter mode of operation
|
||||
* - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf.
|
||||
*
|
||||
* Unicode multi-byte character safe
|
||||
*
|
||||
* @param plaintext source text to be encrypted
|
||||
* @param password the password to use to generate a key
|
||||
* @param nBits number of bits to be used in the key (128, 192, or 256)
|
||||
*
|
||||
* @return encrypted text
|
||||
*/
|
||||
public static function AESEncryptCtr($plaintext, $password, $nBits)
|
||||
{
|
||||
$blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
|
||||
if (!($nBits == 128 || $nBits == 192 || $nBits == 256)) {
|
||||
return '';
|
||||
} // standard allows 128/192/256 bit keys
|
||||
// note PHP (5) gives us plaintext and password in UTF8 encoding!
|
||||
|
||||
// use AES itself to encrypt password to get cipher key (using plain password as source for
|
||||
// key expansion) - gives us well encrypted key
|
||||
$nBytes = $nBits / 8; // no bytes in key
|
||||
$pwBytes = array();
|
||||
for ($i = 0; $i < $nBytes; ++$i) {
|
||||
$pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
|
||||
}
|
||||
$key = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
|
||||
$key = array_merge($key, array_slice($key, 0, $nBytes - 16)); // expand key to 16/24/32 bytes long
|
||||
|
||||
// initialise counter block (NIST SP800-38A <20>B.2): millisecond time-stamp for nonce in
|
||||
// 1st 8 bytes, block counter in 2nd 8 bytes
|
||||
$counterBlock = array();
|
||||
$nonce = floor(microtime(true) * 1000); // timestamp: milliseconds since 1-Jan-1970
|
||||
$nonceSec = floor($nonce / 1000);
|
||||
$nonceMs = $nonce % 1000;
|
||||
// encode nonce with seconds in 1st 4 bytes, and (repeated) ms part filling 2nd 4 bytes
|
||||
for ($i = 0; $i < 4; ++$i) {
|
||||
$counterBlock[$i] = self::urs($nonceSec, $i * 8) & 0xff;
|
||||
}
|
||||
for ($i = 0; $i < 4; ++$i) {
|
||||
$counterBlock[$i + 4] = $nonceMs & 0xff;
|
||||
}
|
||||
// and convert it to a string to go on the front of the ciphertext
|
||||
$ctrTxt = '';
|
||||
for ($i = 0; $i < 8; ++$i) {
|
||||
$ctrTxt .= chr($counterBlock[$i]);
|
||||
}
|
||||
|
||||
// generate key schedule - an expansion of the key into distinct Key Rounds for each round
|
||||
$keySchedule = self::KeyExpansion($key);
|
||||
|
||||
$blockCount = ceil(strlen($plaintext) / $blockSize);
|
||||
$ciphertxt = array(); // ciphertext as array of strings
|
||||
|
||||
for ($b = 0; $b < $blockCount; ++$b) {
|
||||
// set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
|
||||
// done in two stages for 32-bit ops: using two words allows us to go past 2^32 blocks (68GB)
|
||||
for ($c = 0; $c < 4; ++$c) {
|
||||
$counterBlock[15 - $c] = self::urs($b, $c * 8) & 0xff;
|
||||
}
|
||||
for ($c = 0; $c < 4; ++$c) {
|
||||
$counterBlock[15 - $c - 4] = self::urs($b / 0x100000000, $c * 8);
|
||||
}
|
||||
|
||||
$cipherCntr = self::Cipher($counterBlock, $keySchedule); // -- encrypt counter block --
|
||||
|
||||
// block size is reduced on final block
|
||||
$blockLength = $b < $blockCount - 1 ? $blockSize : (strlen($plaintext) - 1) % $blockSize + 1;
|
||||
$cipherByte = array();
|
||||
|
||||
for ($i = 0; $i < $blockLength; ++$i) { // -- xor plaintext with ciphered counter byte-by-byte --
|
||||
$cipherByte[$i] = $cipherCntr[$i] ^ ord(substr($plaintext, $b * $blockSize + $i, 1));
|
||||
$cipherByte[$i] = chr($cipherByte[$i]);
|
||||
}
|
||||
$ciphertxt[$b] = implode('', $cipherByte); // escape troublesome characters in ciphertext
|
||||
}
|
||||
|
||||
// implode is more efficient than repeated string concatenation
|
||||
$ciphertext = $ctrTxt.implode('', $ciphertxt);
|
||||
$ciphertext = base64_encode($ciphertext);
|
||||
|
||||
return $ciphertext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt a text encrypted by AES in counter mode of operation.
|
||||
*
|
||||
* @param ciphertext source text to be decrypted
|
||||
* @param password the password to use to generate a key
|
||||
* @param nBits number of bits to be used in the key (128, 192, or 256)
|
||||
*
|
||||
* @return decrypted text
|
||||
*/
|
||||
public static function AESDecryptCtr($ciphertext, $password, $nBits)
|
||||
{
|
||||
$blockSize = 16; // block size fixed at 16 bytes / 128 bits (Nb=4) for AES
|
||||
if (!($nBits == 128 || $nBits == 192 || $nBits == 256)) {
|
||||
return '';
|
||||
} // standard allows 128/192/256 bit keys
|
||||
$ciphertext = base64_decode($ciphertext);
|
||||
|
||||
// use AES to encrypt password (mirroring encrypt routine)
|
||||
$nBytes = $nBits / 8; // no bytes in key
|
||||
$pwBytes = array();
|
||||
for ($i = 0; $i < $nBytes; ++$i) {
|
||||
$pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
|
||||
}
|
||||
$key = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
|
||||
$key = array_merge($key, array_slice($key, 0, $nBytes - 16)); // expand key to 16/24/32 bytes long
|
||||
|
||||
// recover nonce from 1st element of ciphertext
|
||||
$counterBlock = array();
|
||||
$ctrTxt = substr($ciphertext, 0, 8);
|
||||
for ($i = 0; $i < 8; ++$i) {
|
||||
$counterBlock[$i] = ord(substr($ctrTxt, $i, 1));
|
||||
}
|
||||
|
||||
// generate key schedule
|
||||
$keySchedule = self::KeyExpansion($key);
|
||||
|
||||
// separate ciphertext into blocks (skipping past initial 8 bytes)
|
||||
$nBlocks = ceil((strlen($ciphertext) - 8) / $blockSize);
|
||||
$ct = array();
|
||||
for ($b = 0; $b < $nBlocks; ++$b) {
|
||||
$ct[$b] = substr($ciphertext, 8 + $b * $blockSize, 16);
|
||||
}
|
||||
$ciphertext = $ct; // ciphertext is now array of block-length strings
|
||||
|
||||
// plaintext will get generated block-by-block into array of block-length strings
|
||||
$plaintxt = array();
|
||||
|
||||
for ($b = 0; $b < $nBlocks; ++$b) {
|
||||
// set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)
|
||||
for ($c = 0; $c < 4; ++$c) {
|
||||
$counterBlock[15 - $c] = self::urs($b, $c * 8) & 0xff;
|
||||
}
|
||||
for ($c = 0; $c < 4; ++$c) {
|
||||
$counterBlock[15 - $c - 4] = self::urs(($b + 1) / 0x100000000 - 1, $c * 8) & 0xff;
|
||||
}
|
||||
|
||||
$cipherCntr = self::Cipher($counterBlock, $keySchedule); // encrypt counter block
|
||||
|
||||
$plaintxtByte = array();
|
||||
for ($i = 0; $i < strlen($ciphertext[$b]); ++$i) {
|
||||
// -- xor plaintext with ciphered counter byte-by-byte --
|
||||
$plaintxtByte[$i] = $cipherCntr[$i] ^ ord(substr($ciphertext[$b], $i, 1));
|
||||
$plaintxtByte[$i] = chr($plaintxtByte[$i]);
|
||||
}
|
||||
$plaintxt[$b] = implode('', $plaintxtByte);
|
||||
}
|
||||
|
||||
// join array of blocks into single plaintext string
|
||||
$plaintext = implode('', $plaintxt);
|
||||
|
||||
return $plaintext;
|
||||
}
|
||||
|
||||
/**
|
||||
* AES encryption in CBC mode. This is the standard mode (the CTR methods
|
||||
* actually use Rijndael-128 in CTR mode, which - technically - isn't AES).
|
||||
* The data length is tucked as a 32-bit unsigned integer (little endian)
|
||||
* after the ciphertext. It supports AES-128, AES-192 and AES-256.
|
||||
*
|
||||
* @since 3.0.1
|
||||
*
|
||||
* @author Nicholas K. Dionysopoulos
|
||||
*
|
||||
* @param string $plaintext The data to encrypt
|
||||
* @param string $password Encryption password
|
||||
* @param int $nBits Encryption key size. Can be 128, 192 or 256
|
||||
*
|
||||
* @return string The ciphertext
|
||||
*/
|
||||
public static function AESEncryptCBC($plaintext, $password, $nBits = 128)
|
||||
{
|
||||
if (!($nBits == 128 || $nBits == 192 || $nBits == 256)) {
|
||||
return false;
|
||||
} // standard allows 128/192/256 bit keys
|
||||
if (!function_exists('mcrypt_module_open')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try to fetch cached key/iv or create them if they do not exist
|
||||
$lookupKey = $password.'-'.$nBits;
|
||||
if (array_key_exists($lookupKey, self::$passwords)) {
|
||||
$key = self::$passwords[$lookupKey]['key'];
|
||||
$iv = self::$passwords[$lookupKey]['iv'];
|
||||
} else {
|
||||
// use AES itself to encrypt password to get cipher key (using plain password as source for
|
||||
// key expansion) - gives us well encrypted key
|
||||
$nBytes = $nBits / 8; // no bytes in key
|
||||
$pwBytes = array();
|
||||
for ($i = 0; $i < $nBytes; ++$i) {
|
||||
$pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
|
||||
}
|
||||
$key = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
|
||||
$key = array_merge($key, array_slice($key, 0, $nBytes - 16)); // expand key to 16/24/32 bytes long
|
||||
$newKey = '';
|
||||
foreach ($key as $int) {
|
||||
$newKey .= chr($int);
|
||||
}
|
||||
$key = $newKey;
|
||||
|
||||
// Create an Initialization Vector (IV) based on the password, using the same technique as for the key
|
||||
$nBytes = 16; // AES uses a 128 -bit (16 byte) block size, hence the IV size is always 16 bytes
|
||||
$pwBytes = array();
|
||||
for ($i = 0; $i < $nBytes; ++$i) {
|
||||
$pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
|
||||
}
|
||||
$iv = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
|
||||
$newIV = '';
|
||||
foreach ($iv as $int) {
|
||||
$newIV .= chr($int);
|
||||
}
|
||||
$iv = $newIV;
|
||||
|
||||
self::$passwords[$lookupKey]['key'] = $key;
|
||||
self::$passwords[$lookupKey]['iv'] = $iv;
|
||||
}
|
||||
|
||||
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
|
||||
mcrypt_generic_init($td, $key, $iv);
|
||||
$ciphertext = mcrypt_generic($td, $plaintext);
|
||||
mcrypt_generic_deinit($td);
|
||||
|
||||
$ciphertext .= pack('V', strlen($plaintext));
|
||||
|
||||
return $ciphertext;
|
||||
}
|
||||
|
||||
/**
|
||||
* AES decryption in CBC mode. This is the standard mode (the CTR methods
|
||||
* actually use Rijndael-128 in CTR mode, which - technically - isn't AES).
|
||||
*
|
||||
* Supports AES-128, AES-192 and AES-256. It supposes that the last 4 bytes
|
||||
* contained a little-endian unsigned long integer representing the unpadded
|
||||
* data length.
|
||||
*
|
||||
* @since 3.0.1
|
||||
*
|
||||
* @author Nicholas K. Dionysopoulos
|
||||
*
|
||||
* @param string $ciphertext The data to encrypt
|
||||
* @param string $password Encryption password
|
||||
* @param int $nBits Encryption key size. Can be 128, 192 or 256
|
||||
*
|
||||
* @return string The plaintext
|
||||
*/
|
||||
public static function AESDecryptCBC($ciphertext, $password, $nBits = 128)
|
||||
{
|
||||
if (!($nBits == 128 || $nBits == 192 || $nBits == 256)) {
|
||||
return false;
|
||||
} // standard allows 128/192/256 bit keys
|
||||
if (!function_exists('mcrypt_module_open')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Try to fetch cached key/iv or create them if they do not exist
|
||||
$lookupKey = $password.'-'.$nBits;
|
||||
if (array_key_exists($lookupKey, self::$passwords)) {
|
||||
$key = self::$passwords[$lookupKey]['key'];
|
||||
$iv = self::$passwords[$lookupKey]['iv'];
|
||||
} else {
|
||||
// use AES itself to encrypt password to get cipher key (using plain password as source for
|
||||
// key expansion) - gives us well encrypted key
|
||||
$nBytes = $nBits / 8; // no bytes in key
|
||||
$pwBytes = array();
|
||||
for ($i = 0; $i < $nBytes; ++$i) {
|
||||
$pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
|
||||
}
|
||||
$key = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
|
||||
$key = array_merge($key, array_slice($key, 0, $nBytes - 16)); // expand key to 16/24/32 bytes long
|
||||
$newKey = '';
|
||||
foreach ($key as $int) {
|
||||
$newKey .= chr($int);
|
||||
}
|
||||
$key = $newKey;
|
||||
|
||||
// Create an Initialization Vector (IV) based on the password, using the same technique as for the key
|
||||
$nBytes = 16; // AES uses a 128 -bit (16 byte) block size, hence the IV size is always 16 bytes
|
||||
$pwBytes = array();
|
||||
for ($i = 0; $i < $nBytes; ++$i) {
|
||||
$pwBytes[$i] = ord(substr($password, $i, 1)) & 0xff;
|
||||
}
|
||||
$iv = self::Cipher($pwBytes, self::KeyExpansion($pwBytes));
|
||||
$newIV = '';
|
||||
foreach ($iv as $int) {
|
||||
$newIV .= chr($int);
|
||||
}
|
||||
$iv = $newIV;
|
||||
|
||||
self::$passwords[$lookupKey]['key'] = $key;
|
||||
self::$passwords[$lookupKey]['iv'] = $iv;
|
||||
}
|
||||
|
||||
// Read the data size
|
||||
$data_size = unpack('V', substr($ciphertext, -4));
|
||||
|
||||
// Decrypt
|
||||
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
|
||||
mcrypt_generic_init($td, $key, $iv);
|
||||
$plaintext = mdecrypt_generic($td, substr($ciphertext, 0, -4));
|
||||
mcrypt_generic_deinit($td);
|
||||
|
||||
// Trim padding, if necessary
|
||||
if (strlen($plaintext) > $data_size) {
|
||||
$plaintext = substr($plaintext, 0, $data_size);
|
||||
}
|
||||
|
||||
return $plaintext;
|
||||
}
|
||||
}
|
||||
281
components/com_jce/editor/libraries/classes/extensions.php
Normal file
281
components/com_jce/editor/libraries/classes/extensions.php
Normal file
@@ -0,0 +1,281 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
// set as an extension parent
|
||||
if (!defined('_WF_EXT')) {
|
||||
define('_WF_EXT', 1);
|
||||
}
|
||||
|
||||
class WFExtension extends JObject
|
||||
{
|
||||
/**
|
||||
* Constructor activating the default information of the class.
|
||||
*/
|
||||
public function __construct($config = array())
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// set extension properties
|
||||
$this->setProperties($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to a WFExtension object.
|
||||
*
|
||||
* This method must be invoked as:
|
||||
* <pre> $extension = WFExtension::getInstance();</pre>
|
||||
*
|
||||
* @return object WFExtension
|
||||
*/
|
||||
/* public static function getInstance()
|
||||
{
|
||||
static $instance;
|
||||
|
||||
if (!is_object($instance)) {
|
||||
$instance = new WFExtension();
|
||||
}
|
||||
return $instance;
|
||||
} */
|
||||
|
||||
/**
|
||||
* Display the extension.
|
||||
*/
|
||||
public function display()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a plugin extension.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private static function _load($types = array(), $extension = null, $config = array())
|
||||
{
|
||||
jimport('joomla.filesystem.folder');
|
||||
jimport('joomla.filesystem.file');
|
||||
|
||||
$language = JFactory::getLanguage();
|
||||
|
||||
$extensions = array();
|
||||
|
||||
if (!isset($config['base_path'])) {
|
||||
$config['base_path'] = WF_EDITOR;
|
||||
}
|
||||
|
||||
// core extensions path
|
||||
$path = $config['base_path'] . '/extensions';
|
||||
|
||||
// cast as array
|
||||
$types = (array) $types;
|
||||
|
||||
// get all installed plugins
|
||||
$installed = JPluginHelper::getPlugin('jce');
|
||||
|
||||
if (!empty($installed)) {
|
||||
foreach ($installed as $p) {
|
||||
|
||||
// check for delimiter, only load "extensions"
|
||||
if (strpos($p->name, '-') === false || strpos($p->name, 'editor-') !== false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// set path
|
||||
$p->path = JPATH_PLUGINS . '/jce/' . $p->name;
|
||||
|
||||
// get type and name
|
||||
$parts = explode('-', $p->name);
|
||||
$p->folder = $parts[0];
|
||||
$p->extension = $parts[1];
|
||||
|
||||
// load the correct type if set
|
||||
if (!empty($types) && !in_array($p->folder, $types)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// specific extension
|
||||
if ($extension && $p->extension !== $extension) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$language->load('plg_jce_' . $p->name, JPATH_ADMINISTRATOR);
|
||||
$language->load('plg_jce_' . $p->name, $p->path);
|
||||
|
||||
// add to array
|
||||
$extensions[$p->extension] = $p;
|
||||
}
|
||||
}
|
||||
|
||||
// get legacy extensions
|
||||
$legacy = JFolder::folders(WF_EDITOR . '/extensions', '.', false, true);
|
||||
|
||||
$core = array(
|
||||
'aggregator' => array(
|
||||
'dailymotion', 'vimeo', 'youtube',
|
||||
),
|
||||
'filesystem' => array(
|
||||
'joomla',
|
||||
),
|
||||
'links' => array(
|
||||
'joomlalinks',
|
||||
),
|
||||
'popups' => array(
|
||||
'jcemediabox',
|
||||
),
|
||||
'search' => array(
|
||||
'link',
|
||||
),
|
||||
);
|
||||
|
||||
foreach ($legacy as $item) {
|
||||
$type = basename($item);
|
||||
|
||||
// unknown type
|
||||
if (array_key_exists($type, $core) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// load the correct type if set
|
||||
if (!empty($types) && !in_array($type, $types)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// specific extension
|
||||
if ($extension && !JFile::exists($item . '/' . $extension . '.php')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!empty($extension)) {
|
||||
// already loaded as Joomla plugin
|
||||
if (isset($extensions[$extension])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$files = array($item . '/' . $extension . '.xml');
|
||||
} else {
|
||||
$files = JFolder::files($item, '\.xml$', false, true);
|
||||
}
|
||||
|
||||
foreach ($files as $file) {
|
||||
$extension = basename($file, '.xml');
|
||||
|
||||
// unknown extension
|
||||
if (!in_array($extension, $core[$type])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$object = new stdClass();
|
||||
$object->folder = $type;
|
||||
$object->path = dirname($file);
|
||||
$object->extension = $extension;
|
||||
|
||||
if (!isset($extensions[$extension])) {
|
||||
$extensions[$extension] = $object;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $extensions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load & Call an extension.
|
||||
*
|
||||
* @param array $config
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public static function loadExtensions($type, $extension = null, $config = array())
|
||||
{
|
||||
jimport('joomla.filesystem.folder');
|
||||
jimport('joomla.filesystem.file');
|
||||
|
||||
if (!isset($config['base_path'])) {
|
||||
$config['base_path'] = WF_EDITOR;
|
||||
}
|
||||
|
||||
// sanitize $type
|
||||
$type = preg_replace('#[^A-Z0-9\._-]#i', '', $type);
|
||||
|
||||
// sanitize $extension
|
||||
if ($extension) {
|
||||
$extension = preg_replace('#[^A-Z0-9\._-]#i', '', $extension);
|
||||
}
|
||||
|
||||
// Get all extensions
|
||||
$extensions = self::_load((array) $type, $extension, $config);
|
||||
|
||||
$result = array();
|
||||
|
||||
if (!empty($extensions)) {
|
||||
foreach ($extensions as $item) {
|
||||
$name = isset($item->extension) ? $item->extension : '';
|
||||
|
||||
$type = $item->folder;
|
||||
$path = $item->path;
|
||||
|
||||
if ($name) {
|
||||
$root = $path . '/' . basename($path) . '.php';
|
||||
|
||||
// store name in item object
|
||||
$item->name = $name;
|
||||
|
||||
// legacy - clean defined path for Windows!!
|
||||
if (WFUtility::cleanPath(dirname($path)) === WFUtility::cleanPath(WF_EDITOR_EXTENSIONS)) {
|
||||
$root = $path . '/' . $name . '.php';
|
||||
// redefine path
|
||||
$item->path = $path . '/' . $name;
|
||||
}
|
||||
|
||||
if (file_exists($root)) {
|
||||
// Load root extension file
|
||||
require_once $root;
|
||||
|
||||
// Return array of extension names
|
||||
$result[$type][] = $item;
|
||||
|
||||
// if we only want a named extension
|
||||
if ($extension && $extension == $name) {
|
||||
return $item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// only return extension types requested
|
||||
if ($type && array_key_exists($type, $result)) {
|
||||
return $result[$type];
|
||||
}
|
||||
|
||||
// Return array or extension name
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a parameter for the current plugin / group.
|
||||
*
|
||||
* @param object $key Parameter name
|
||||
* @param object $default Default value
|
||||
*
|
||||
* @return string Parameter value
|
||||
*/
|
||||
public function getParam($key, $default = '')
|
||||
{
|
||||
$wf = WFApplication::getInstance();
|
||||
|
||||
return $wf->getParam($key, $default);
|
||||
}
|
||||
|
||||
public function getView($options = array())
|
||||
{
|
||||
return new WFView($options);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
class WFAggregatorExtension extends WFExtension
|
||||
{
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* Returns a reference to a plugin object.
|
||||
*
|
||||
* This method must be invoked as:
|
||||
* <pre> $advlink =AdvLink::getInstance();</pre>
|
||||
*
|
||||
* @return JCE The editor object
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public static function getInstance($config = array())
|
||||
{
|
||||
if (!isset(self::$instance)) {
|
||||
self::$instance = new self($config);
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->get('name');
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->get('title');
|
||||
}
|
||||
|
||||
public function display()
|
||||
{
|
||||
parent::display();
|
||||
|
||||
$document = WFDocument::getInstance();
|
||||
|
||||
$aggregators = $this->getAggregators();
|
||||
|
||||
foreach ($aggregators as $aggregator) {
|
||||
$aggregator->display();
|
||||
|
||||
$params = $aggregator->getParams();
|
||||
|
||||
if (!empty($params)) {
|
||||
$document->addScriptDeclaration('WFExtensions.Aggregator.setParams("' . $aggregator->getName() . '",' . json_encode($params) . ');');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getAggregators()
|
||||
{
|
||||
static $aggregators;
|
||||
|
||||
if (!isset($aggregators)) {
|
||||
$aggregators = array();
|
||||
}
|
||||
|
||||
// get the aggregator format for this instance
|
||||
$format = $this->get('format');
|
||||
|
||||
if (empty($aggregators[$format])) {
|
||||
jimport('joomla.filesystem.folder');
|
||||
|
||||
// get a plugin instance
|
||||
$plugin = WFEditorPlugin::getInstance();
|
||||
|
||||
$aggregators[$format] = array();
|
||||
|
||||
$path = WF_EDITOR_EXTENSIONS . '/aggregator';
|
||||
$files = JFolder::files($path, '\.php$', false, true);
|
||||
|
||||
foreach ($files as $file) {
|
||||
require_once $file;
|
||||
|
||||
$name = basename($file, '.php');
|
||||
$classname = 'WFAggregatorExtension_' . ucfirst($name);
|
||||
|
||||
// only load if enabled
|
||||
if (class_exists($classname)) {
|
||||
$aggregator = new $classname();
|
||||
|
||||
// check if enabled
|
||||
if ($aggregator->isEnabled()) {
|
||||
if ($aggregator->get('format') == $format) {
|
||||
$aggregator->set('name', $name);
|
||||
$aggregator->set('title', 'WF_AGGREGATOR_' . strtoupper($name) . '_TITLE');
|
||||
$aggregators[$format][] = $aggregator;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $aggregators[$format];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object $player
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function loadTemplate($name, $tpl = '')
|
||||
{
|
||||
$path = WF_EDITOR_EXTENSIONS . '/aggregator/' . $name;
|
||||
|
||||
$output = '';
|
||||
|
||||
$file = 'default.php';
|
||||
|
||||
if ($tpl) {
|
||||
$file = 'default_' . $tpl . '.php';
|
||||
}
|
||||
|
||||
if (file_exists($path . '/tmpl/' . $file)) {
|
||||
ob_start();
|
||||
|
||||
include $path . '/tmpl/' . $file;
|
||||
|
||||
$output .= ob_get_contents();
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,399 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
class WFFileSystem extends WFExtension
|
||||
{
|
||||
/**
|
||||
* Constructor activating the default information of the class.
|
||||
*/
|
||||
public function __construct($config = array())
|
||||
{
|
||||
parent::__construct($config);
|
||||
|
||||
$this->setProperties(array_merge($config, array(
|
||||
'local' => true,
|
||||
)));
|
||||
|
||||
// get path variable properties
|
||||
$vars = $this->getPathVariables();
|
||||
|
||||
// assign to instance
|
||||
$this->setProperties($vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to a plugin object.
|
||||
*
|
||||
* This method must be invoked as:
|
||||
* <pre> $advlink =AdvLink::getInstance();</pre>
|
||||
*
|
||||
* @return JCE The editor object
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public static function getInstance($type = 'joomla', $config = array())
|
||||
{
|
||||
static $instances = array();
|
||||
|
||||
$signature = md5($type . serialize($config));
|
||||
|
||||
if (!isset($instances[$signature])) {
|
||||
$fs = parent::loadExtensions('filesystem', $type);
|
||||
|
||||
// load the default...
|
||||
if (empty($fs)) {
|
||||
$fs = parent::loadExtensions('filesystem', 'joomla');
|
||||
}
|
||||
|
||||
// get the first filesystem extension only
|
||||
if (is_array($fs)) {
|
||||
$fs = array_shift($fs);
|
||||
}
|
||||
|
||||
$classname = 'WF' . ucfirst($fs->name) . 'FileSystem';
|
||||
|
||||
if (class_exists($classname)) {
|
||||
$instances[$signature] = new $classname($config);
|
||||
} else {
|
||||
$instances[$signature] = new self($config);
|
||||
}
|
||||
}
|
||||
|
||||
return $instances[$signature];
|
||||
}
|
||||
|
||||
public function updateOptions(&$options)
|
||||
{
|
||||
$options['dir'] = $this->getRootDir();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base directory.
|
||||
*
|
||||
* @return string base dir
|
||||
*/
|
||||
public function getBaseDir()
|
||||
{
|
||||
return WFUtility::makePath(JPATH_SITE, $this->getRootDir());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full base url.
|
||||
*
|
||||
* @return string base url
|
||||
*/
|
||||
public function getBaseURL()
|
||||
{
|
||||
return WFUtility::makePath(JURI::root(true), $this->getRootDir());
|
||||
}
|
||||
|
||||
private function getPathVariables()
|
||||
{
|
||||
static $variables;
|
||||
|
||||
if (!isset($variables)) {
|
||||
$user = JFactory::getUser();
|
||||
$wf = WFApplication::getInstance();
|
||||
$profile = $wf->getProfile();
|
||||
|
||||
jimport('joomla.user.helper');
|
||||
|
||||
$groups = JUserHelper::getUserGroups($user->id);
|
||||
|
||||
// get keys only
|
||||
$groups = array_keys($groups);
|
||||
|
||||
// get the first group
|
||||
$group_id = array_shift($groups);
|
||||
|
||||
if (is_int($group_id)) {
|
||||
// usergroup table
|
||||
$group = JTable::getInstance('Usergroup');
|
||||
$group->load($group_id);
|
||||
// usertype
|
||||
$usertype = $group->title;
|
||||
} else {
|
||||
$usertype = $group_id;
|
||||
}
|
||||
|
||||
// Replace any path variables
|
||||
$path_pattern = array('/\$id/', '/\$username/', '/\$name/', '/\$user(group|type)/', '/\$(group|profile)/', '/\$day/', '/\$month/', '/\$year/');
|
||||
$path_replacement = array($user->id, $user->username, $user->name, $usertype, $profile->name, date('d'), date('m'), date('Y'));
|
||||
|
||||
$websafe_textcase = $wf->getParam('editor.websafe_textcase', '');
|
||||
|
||||
// implode textcase array to create string
|
||||
if (is_array($websafe_textcase)) {
|
||||
$websafe_textcase = implode(',', $websafe_textcase);
|
||||
}
|
||||
|
||||
$websafe_mode = $wf->getParam('editor.websafe_mode', 'utf-8');
|
||||
$websafe_allow_spaces = $wf->getParam('editor.websafe_allow_spaces', '_');
|
||||
|
||||
$variables = compact('path_pattern', 'path_replacement', 'websafe_textcase', 'websafe_mode', 'websafe_allow_spaces');
|
||||
}
|
||||
|
||||
return $variables;
|
||||
}
|
||||
|
||||
public function processPath(&$path)
|
||||
{
|
||||
$path = preg_replace($this->get('path_pattern', array()), $this->get('path_replacement', array()), $path);
|
||||
|
||||
// split into path parts to preserve /
|
||||
$parts = explode('/', $path);
|
||||
|
||||
// clean path parts
|
||||
$parts = WFUtility::makeSafe($parts, $this->get('websafe_mode', 'utf-8'), $this->get('websafe_allow_spaces', '_'), $this->get('websafe_textcase', ''));
|
||||
|
||||
// join path parts
|
||||
$path = implode('/', $parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the full user directory path. Create if required.
|
||||
*
|
||||
* @param string The base path
|
||||
*
|
||||
* @return Full path to folder
|
||||
*/
|
||||
public function getRootDir()
|
||||
{
|
||||
static $root;
|
||||
|
||||
if (!isset($root)) {
|
||||
// Get base directory as shared parameter
|
||||
$root = $this->get('dir', '');
|
||||
|
||||
// Remove whitespace
|
||||
$root = trim($root);
|
||||
|
||||
if (!empty($root)) {
|
||||
// Convert slashes / Strip double slashes
|
||||
$root = preg_replace('/[\\\\]+/', '/', $root);
|
||||
|
||||
// Remove first leading slash
|
||||
$root = ltrim($root, '/');
|
||||
|
||||
// Force default directory if base param is now empty or starts with a variable or a . eg $id
|
||||
if (empty($root) || preg_match('/[\.\$]/', $root[0])) {
|
||||
$root = 'images';
|
||||
}
|
||||
|
||||
$this->processPath($root);
|
||||
}
|
||||
}
|
||||
|
||||
return $root;
|
||||
}
|
||||
|
||||
protected static function sortItemsByKey($items, $type)
|
||||
{
|
||||
$sortable = array();
|
||||
|
||||
// set default direction
|
||||
$direction = 'asc';
|
||||
|
||||
if ($type[0] === '-') {
|
||||
$direction = 'desc';
|
||||
$type = substr($type, 1);
|
||||
}
|
||||
|
||||
foreach ($items as $key => $item) {
|
||||
$sortable[$key] = isset($item[$type]) ? $item[$type] : $item['properties'][$type];
|
||||
}
|
||||
|
||||
array_multisort($sortable, $direction === 'desc' ? SORT_DESC : SORT_ASC, SORT_NATURAL | SORT_FLAG_CASE, $items);
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
public function toAbsolute($path)
|
||||
{
|
||||
return $path;
|
||||
}
|
||||
|
||||
public function toRelative($path)
|
||||
{
|
||||
return $path;
|
||||
}
|
||||
|
||||
public function getTotalSize($path, $recurse = true)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function countFiles($path, $recurse = false)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getFiles($path, $filter)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getFolders($path, $filter)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
public function getSourceDir($path)
|
||||
{
|
||||
return $path;
|
||||
}
|
||||
|
||||
public function isMatch($needle, $haystack)
|
||||
{
|
||||
return $needle == $haystack;
|
||||
}
|
||||
|
||||
public function pathinfo($path)
|
||||
{
|
||||
return pathinfo($path);
|
||||
}
|
||||
|
||||
public function delete($path)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function createFolder($path, $new)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rename($src, $dest)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function copy($src, $dest)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function move($src, $dest)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getFolderDetails($path)
|
||||
{
|
||||
return array(
|
||||
'properties' => array('modified' => ''),
|
||||
);
|
||||
}
|
||||
|
||||
public function getFileDetails($path)
|
||||
{
|
||||
$data = array(
|
||||
'properties' => array(
|
||||
'size' => '',
|
||||
'modified' => '',
|
||||
),
|
||||
);
|
||||
|
||||
if (preg_match('#\.(jpg|jpeg|bmp|gif|tiff|png)#i', $path)) {
|
||||
$image = array(
|
||||
'properties' => array(
|
||||
'width' => 0,
|
||||
'height' => 0,
|
||||
'preview' => '',
|
||||
),
|
||||
);
|
||||
|
||||
return array_merge_recursive($data, $image);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getDimensions($path)
|
||||
{
|
||||
return array(
|
||||
'width' => '',
|
||||
'height' => '',
|
||||
);
|
||||
}
|
||||
|
||||
public function upload($method, $src, $dir, $name, $chunks = 0, $chunk = 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function exists($path)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function read($path)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function write($path, $content)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function isLocal()
|
||||
{
|
||||
return $this->get('local') === true;
|
||||
}
|
||||
|
||||
public function is_file($path)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function is_dir($path)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filesystem Error class.
|
||||
*/
|
||||
final class WFFileSystemResult
|
||||
{
|
||||
/*
|
||||
* @var Object type eg: file / folder
|
||||
*/
|
||||
|
||||
public $type = 'files';
|
||||
/*
|
||||
* @boolean Result state
|
||||
*/
|
||||
public $state = false;
|
||||
/*
|
||||
* @int Error code
|
||||
*/
|
||||
public $code = null;
|
||||
/*
|
||||
* @var Error message
|
||||
*/
|
||||
public $message = null;
|
||||
/*
|
||||
* @var File / Folder path
|
||||
*/
|
||||
public $path = null;
|
||||
/*
|
||||
* @var File / Folder url
|
||||
*/
|
||||
public $url = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
||||
241
components/com_jce/editor/libraries/classes/extensions/link.php
Normal file
241
components/com_jce/editor/libraries/classes/extensions/link.php
Normal file
@@ -0,0 +1,241 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
class WFLinkExtension extends WFExtension
|
||||
{
|
||||
/*
|
||||
* @var varchar
|
||||
*/
|
||||
|
||||
private $extensions = array();
|
||||
protected static $instance;
|
||||
protected static $links = array();
|
||||
|
||||
/**
|
||||
* Constructor activating the default information of the class.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$extensions = self::loadExtensions('links');
|
||||
|
||||
// Load all link extensions
|
||||
foreach ($extensions as $link) {
|
||||
$this->extensions[] = $this->getLinkExtension($link->name);
|
||||
}
|
||||
|
||||
$request = WFRequest::getInstance();
|
||||
$request->setRequest(array($this, 'getLinks'));
|
||||
}
|
||||
|
||||
public static function getInstance($config = array())
|
||||
{
|
||||
if (!isset(self::$instance)) {
|
||||
self::$instance = new self($config);
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function display()
|
||||
{
|
||||
parent::display();
|
||||
|
||||
foreach ($this->extensions as $extension) {
|
||||
$extension->display();
|
||||
}
|
||||
}
|
||||
|
||||
private function getLinkExtension($name)
|
||||
{
|
||||
if (array_key_exists($name, self::$links) === false || empty(self::$links[$name])) {
|
||||
$classname = 'WFLinkBrowser_' . ucfirst($name);
|
||||
// create class
|
||||
if (class_exists($classname)) {
|
||||
self::$links[$name] = new $classname();
|
||||
}
|
||||
}
|
||||
|
||||
return self::$links[$name];
|
||||
}
|
||||
|
||||
public function getLists()
|
||||
{
|
||||
$list = array();
|
||||
|
||||
foreach ($this->extensions as $extension) {
|
||||
if ($extension->isEnabled()) {
|
||||
$list[] = $extension->getList();
|
||||
}
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
$list = $this->getLists();
|
||||
|
||||
if (empty($list)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$view = $this->getView(array('name' => 'links', 'layout' => 'links'));
|
||||
$view->list = implode("\n", $list);
|
||||
$view->display();
|
||||
}
|
||||
|
||||
private static function cleanInput($args, $method = 'string')
|
||||
{
|
||||
$filter = JFilterInput::getInstance();
|
||||
|
||||
foreach ($args as $k => $v) {
|
||||
$args->$k = $filter->clean($v, $method);
|
||||
$args->$k = (string) filter_var($args->$k, FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_BACKTICK);
|
||||
$args->$k = htmlspecialchars(strip_tags($args->$k));
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
public function getLinks($args)
|
||||
{
|
||||
$args = self::cleanInput($args, 'STRING');
|
||||
|
||||
foreach ($this->extensions as $extension) {
|
||||
if (in_array($args->option, $extension->getOption())) {
|
||||
$items = $extension->getLinks($args);
|
||||
}
|
||||
}
|
||||
$array = array();
|
||||
$result = array();
|
||||
if (isset($items)) {
|
||||
foreach ($items as $item) {
|
||||
$array[] = array(
|
||||
'id' => isset($item['id']) ? self::xmlEncode($item['id']) : '',
|
||||
'url' => isset($item['url']) ? self::xmlEncode($item['url']) : '',
|
||||
'name' => self::xmlEncode($item['name']), 'class' => $item['class'],
|
||||
);
|
||||
}
|
||||
$result = array('folders' => $array);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Category function used by many extensions.
|
||||
*
|
||||
* @return Category list object
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public static function getCategory($section, $parent = 1)
|
||||
{
|
||||
$db = JFactory::getDBO();
|
||||
$user = JFactory::getUser();
|
||||
$wf = WFEditorPlugin::getInstance();
|
||||
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
$where = array();
|
||||
|
||||
$version = new JVersion();
|
||||
$language = $version->isCompatible('3.0') ? ', language' : '';
|
||||
|
||||
$where[] = 'parent_id = ' . (int) $parent;
|
||||
$where[] = 'extension = ' . $db->Quote($section);
|
||||
|
||||
if (!$user->authorise('core.admin')) {
|
||||
$where[] = 'access IN (' . implode(',', $user->getAuthorisedViewLevels()) . ')';
|
||||
}
|
||||
|
||||
if (!$wf->checkAccess('static', 1)) {
|
||||
$where[] = 'path != ' . $db->Quote('uncategorised');
|
||||
}
|
||||
|
||||
$case = '';
|
||||
|
||||
if ($wf->getParam('category_alias', 1) == 1) {
|
||||
//sqlsrv changes
|
||||
$case = ', CASE WHEN ';
|
||||
$case .= $query->charLength('alias', '!=', '0');
|
||||
$case .= ' THEN ';
|
||||
$a_id = $query->castAsChar('id');
|
||||
$case .= $query->concatenate(array($a_id, 'alias'), ':');
|
||||
$case .= ' ELSE ';
|
||||
$case .= $a_id . ' END as slug';
|
||||
}
|
||||
|
||||
$where[] = 'published = 1';
|
||||
$query->select('id AS slug, id AS id, title, alias, access' . $language . $case)->from('#__categories')->where($where)->order('title');
|
||||
|
||||
$db->setQuery($query);
|
||||
|
||||
return $db->loadObjectList();
|
||||
}
|
||||
|
||||
/**
|
||||
* (Attempt to) Get an Itemid.
|
||||
*
|
||||
* @param string $component
|
||||
* @param array $needles
|
||||
*
|
||||
* @return Category list object
|
||||
*/
|
||||
public function getItemId($component, $needles = array())
|
||||
{
|
||||
$match = null;
|
||||
|
||||
//require_once(JPATH_SITE . '/includes/application.php');
|
||||
$app = JApplication::getInstance('site');
|
||||
|
||||
$tag = defined('JPATH_PLATFORM') ? 'component_id' : 'componentid';
|
||||
|
||||
$component = JComponentHelper::getComponent($component);
|
||||
$menu = $app->getMenu('site');
|
||||
$items = $menu->getItems($tag, $component->id);
|
||||
|
||||
if ($items) {
|
||||
foreach ($needles as $needle => $id) {
|
||||
foreach ($items as $item) {
|
||||
if ((@$item->query['view'] == $needle) && (@$item->query['id'] == $id)) {
|
||||
$match = $item->id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isset($match)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $match ? '&Itemid=' . $match : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* XML encode a string.
|
||||
*
|
||||
* @param string String to encode
|
||||
*
|
||||
* @return string Encoded string
|
||||
*/
|
||||
private static function xmlEncode($string)
|
||||
{
|
||||
return str_replace(array('&', '<', '>', "'", '"'), array('&', '<', '>', ''', '"'), $string);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class WFLinkBrowser extends WFLinkExtension
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
class WFMediaPlayerExtension extends WFExtension
|
||||
{
|
||||
protected static $instance;
|
||||
|
||||
public function __construct($config = array())
|
||||
{
|
||||
$default = array(
|
||||
'name' => '',
|
||||
'title' => '',
|
||||
'params' => array(),
|
||||
);
|
||||
|
||||
$config = array_merge($default, $config);
|
||||
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to a manager object.
|
||||
*
|
||||
* This method must be invoked as:
|
||||
* <pre> $manager =MediaManager::getInstance();</pre>
|
||||
*
|
||||
* @return MediaManager The manager object
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public static function getInstance($name = 'jceplayer')
|
||||
{
|
||||
if (!isset(self::$instance)) {
|
||||
$classname = '';
|
||||
|
||||
if ($name && $name != 'none') {
|
||||
$player = parent::loadExtensions('mediaplayer', $name);
|
||||
|
||||
if ($player) {
|
||||
$classname = 'WFMediaPlayerExtension_'.ucfirst($player->name);
|
||||
}
|
||||
}
|
||||
|
||||
if ($classname && class_exists($classname)) {
|
||||
self::$instance = new $classname();
|
||||
} else {
|
||||
self::$instance = new self();
|
||||
}
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function display()
|
||||
{
|
||||
parent::display();
|
||||
|
||||
$document = WFDocument::getInstance();
|
||||
|
||||
if ($this->isEnabled() && $this->get('name')) {
|
||||
$document->addScript(array(
|
||||
'mediaplayer/'.$this->get('name').'/js/'.$this->get('name'),
|
||||
), 'extensions');
|
||||
|
||||
$document->addStyleSheet(array(
|
||||
'mediaplayer/'.$this->get('name').'/css/'.$this->get('name'),
|
||||
), 'extensions');
|
||||
|
||||
$document->addScriptDeclaration('WFExtensions.MediaPlayer.init('.json_encode($this->getProperties()).')');
|
||||
}
|
||||
}
|
||||
|
||||
public function isEnabled()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->get('name');
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
{
|
||||
return $this->get('title');
|
||||
}
|
||||
|
||||
public function getParams()
|
||||
{
|
||||
return $this->params;
|
||||
}
|
||||
|
||||
public function getParam($param, $default = '')
|
||||
{
|
||||
$params = $this->getParams();
|
||||
|
||||
return isset($params[$param]) ? $params[$param] : $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object $player
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function loadTemplate($tpl = '')
|
||||
{
|
||||
$output = '';
|
||||
|
||||
if ($this->isEnabled()) {
|
||||
$path = WF_EDITOR_EXTENSIONS.'/mediaplayer/'.$this->get('name');
|
||||
|
||||
$file = 'default.php';
|
||||
|
||||
if ($tpl) {
|
||||
$file = 'default_'.$tpl.'.php';
|
||||
}
|
||||
|
||||
if (file_exists($path.'/tmpl/'.$file)) {
|
||||
ob_start();
|
||||
|
||||
include $path.'/tmpl/'.$file;
|
||||
|
||||
$output .= ob_get_contents();
|
||||
ob_end_clean();
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
class WFPopupsExtension extends WFExtension
|
||||
{
|
||||
protected static $instance;
|
||||
|
||||
private $_popups = array();
|
||||
private $_templates = array();
|
||||
|
||||
/**
|
||||
* Constructor activating the default information of the class.
|
||||
*/
|
||||
public function __construct($config = array())
|
||||
{
|
||||
parent::__construct($config);
|
||||
|
||||
$this->setProperties($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to a plugin object.
|
||||
*
|
||||
* This method must be invoked as:
|
||||
* <pre> $advlink =AdvLink::getInstance();</pre>
|
||||
*
|
||||
* @return JCE The editor object
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public static function getInstance($config = array())
|
||||
{
|
||||
if (!isset(self::$instance)) {
|
||||
self::$instance = new self($config);
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function display()
|
||||
{
|
||||
parent::display();
|
||||
|
||||
$document = WFDocument::getInstance();
|
||||
|
||||
// get all popups extensions
|
||||
$popups = parent::loadExtensions('popups');
|
||||
|
||||
$config = $this->getProperties();
|
||||
|
||||
if ($config) {
|
||||
// Create global config
|
||||
$document->addScriptDeclaration('WFExtensions.Popups.setConfig(' . json_encode($config) . ');');
|
||||
}
|
||||
|
||||
// Create an instance of each popup and check if enabled
|
||||
foreach ($popups as $item) {
|
||||
$popup = $this->getPopupExtension($item->name);
|
||||
|
||||
if ($popup->isEnabled()) {
|
||||
$this->addPopup($item);
|
||||
|
||||
$params = $popup->getParams();
|
||||
|
||||
if (!empty($params)) {
|
||||
$document->addScriptDeclaration('WFExtensions.Popups.setParams("' . $item->name . '",' . json_encode($params) . ');');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$tabs = WFTabs::getInstance();
|
||||
|
||||
// Add popup tab and assign popups reference to document
|
||||
if (count($this->getPopups())) {
|
||||
$tabs->addTab('popups');
|
||||
$panel = $tabs->getPanel('popups');
|
||||
$panel->popups = $this;
|
||||
}
|
||||
}
|
||||
|
||||
private function getPopups()
|
||||
{
|
||||
return $this->_popups;
|
||||
}
|
||||
|
||||
public function addPopup($popup)
|
||||
{
|
||||
$this->_popups[] = $popup;
|
||||
}
|
||||
|
||||
private function getTemplates()
|
||||
{
|
||||
return $this->_templates;
|
||||
}
|
||||
|
||||
public function addTemplate($template)
|
||||
{
|
||||
$this->_templates[] = $template;
|
||||
}
|
||||
|
||||
private function getPopupExtension($name)
|
||||
{
|
||||
static $popups = array();
|
||||
|
||||
if (!isset($popups[$name])) {
|
||||
$classname = 'WFPopupsExtension_' . ucfirst($name);
|
||||
$popups[$name] = new $classname();
|
||||
}
|
||||
|
||||
return $popups[$name];
|
||||
}
|
||||
|
||||
public function getPopupList()
|
||||
{
|
||||
$options = array();
|
||||
|
||||
$options[] = JHTML::_('select.option', '', '-- ' . JText::_('WF_POPUP_TYPE_SELECT') . ' --');
|
||||
|
||||
foreach ($this->getPopups() as $popup) {
|
||||
$options[] = JHTML::_('select.option', $popup->name, JText::_('WF_POPUPS_' . strtoupper($popup->name) . '_TITLE'));
|
||||
}
|
||||
|
||||
return JHTML::_('select.genericlist', $options, 'popup_list', '', 'value', 'text', $this->get('default'));
|
||||
}
|
||||
|
||||
public function getPopupTemplates()
|
||||
{
|
||||
$output = '';
|
||||
|
||||
foreach ($this->getTemplates() as $template) {
|
||||
$wf = WFEditorPlugin::getInstance();
|
||||
$view = $wf->getView();
|
||||
|
||||
$output .= $view->loadTemplate($template);
|
||||
}
|
||||
|
||||
foreach ($this->getPopups() as $popup) {
|
||||
$view = new WFView(array(
|
||||
'name' => $popup->name,
|
||||
'base_path' => $popup->path,
|
||||
'template_path' => $popup->path . '/tmpl',
|
||||
));
|
||||
|
||||
$instance = $this->getPopupExtension($popup->name);
|
||||
$view->popup = $instance;
|
||||
|
||||
if (file_exists($popup->path . '/tmpl/default.php')) {
|
||||
ob_start();
|
||||
|
||||
$output .= '<div id="popup_extension_' . $popup->name . '" style="display:none;">';
|
||||
|
||||
$view->display();
|
||||
|
||||
$output .= ob_get_contents();
|
||||
$output .= '</div>';
|
||||
ob_end_clean();
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
class WFSearchExtension extends WFExtension
|
||||
{
|
||||
private static $instances = array();
|
||||
|
||||
/**
|
||||
* Returns a reference to a plugin object.
|
||||
*
|
||||
* This method must be invoked as:
|
||||
* <pre> $advlink =AdvLink::getInstance();</pre>
|
||||
*
|
||||
* @return JCE The editor object
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public static function getInstance($type, $config = array())
|
||||
{
|
||||
if (!isset(self::$instances)) {
|
||||
self::$instances = array();
|
||||
}
|
||||
|
||||
if (empty(self::$instances[$type])) {
|
||||
$file = WF_EDITOR . '/extensions/search/' . $type . '.php';
|
||||
|
||||
if (is_file($file)) {
|
||||
require_once WF_EDITOR . '/extensions/search/' . $type . '.php';
|
||||
}
|
||||
|
||||
$classname = 'WF' . ucfirst($type) . 'SearchExtension';
|
||||
|
||||
if (class_exists($classname)) {
|
||||
self::$instances[$type] = new $classname($config);
|
||||
} else {
|
||||
self::$instances[$type] = new self();
|
||||
}
|
||||
}
|
||||
|
||||
return self::$instances[$type];
|
||||
}
|
||||
}
|
||||
1
components/com_jce/editor/libraries/classes/index.html
Normal file
1
components/com_jce/editor/libraries/classes/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
||||
81
components/com_jce/editor/libraries/classes/language.php
Normal file
81
components/com_jce/editor/libraries/classes/language.php
Normal file
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
abstract class WFLanguage
|
||||
{
|
||||
/* Map language code to generic tag */
|
||||
protected static $map = array(
|
||||
'de' => 'de-DE',
|
||||
'fr' => 'fr-FR',
|
||||
);
|
||||
|
||||
/*
|
||||
* Check a language file exists and is the correct version
|
||||
*/
|
||||
protected static function isValid($tag)
|
||||
{
|
||||
return file_exists(JPATH_SITE . '/language/' . $tag . '/' . $tag . '.com_jce.ini');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the curernt language code.
|
||||
*
|
||||
* @return language code
|
||||
*/
|
||||
public static function getDir()
|
||||
{
|
||||
return JFactory::getLanguage()->isRTL() ? 'rtl' : 'ltr';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the curernt language code.
|
||||
*
|
||||
* @return language code
|
||||
*/
|
||||
public static function getTag()
|
||||
{
|
||||
$tag = JFactory::getLanguage()->getTag();
|
||||
|
||||
$code = substr($tag, 0, strpos($tag, '-'));
|
||||
|
||||
if (array_key_exists($code, self::$map)) {
|
||||
$tag = self::$map[$code];
|
||||
}
|
||||
|
||||
if (false == self::isValid($tag)) {
|
||||
return 'en-GB';
|
||||
}
|
||||
|
||||
return $tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the curernt language code.
|
||||
*
|
||||
* @return language code
|
||||
*/
|
||||
public static function getCode()
|
||||
{
|
||||
$tag = self::getTag();
|
||||
|
||||
return substr($tag, 0, strpos($tag, '-'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a language file.
|
||||
*
|
||||
* @param string $prefix Language prefix
|
||||
* @param object $path[optional] Base path
|
||||
*/
|
||||
public static function load($prefix, $path = JPATH_SITE)
|
||||
{
|
||||
JFactory::getLanguage()->load($prefix, $path);
|
||||
}
|
||||
}
|
||||
415
components/com_jce/editor/libraries/classes/languageparser.php
Normal file
415
components/com_jce/editor/libraries/classes/languageparser.php
Normal file
@@ -0,0 +1,415 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
class WFLanguageParser extends JObject
|
||||
{
|
||||
protected $mode = 'editor';
|
||||
protected $plugins = array();
|
||||
protected $sections = array();
|
||||
|
||||
protected $language = 'en-GB';
|
||||
|
||||
/**
|
||||
* Cache of processed data.
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected static $cache = array();
|
||||
|
||||
public function __construct($config = array())
|
||||
{
|
||||
if (array_key_exists('plugins', $config)) {
|
||||
$config['plugins'] = (array) $config['plugins'];
|
||||
}
|
||||
|
||||
if (array_key_exists('sections', $config)) {
|
||||
$config['sections'] = (array) $config['sections'];
|
||||
}
|
||||
|
||||
if (array_key_exists('language', $config)) {
|
||||
$config['language'] = $config['language'];
|
||||
}
|
||||
|
||||
$this->setProperties($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an INI formatted string and convert it into an array.
|
||||
*
|
||||
* @param string $data INI formatted string to convert
|
||||
* @param bool $process_sections A boolean setting to process sections
|
||||
* @param array $sections An array of sections to include
|
||||
* @param mixed $filter A regular expression to filter sections by
|
||||
*
|
||||
* @return array Data array
|
||||
*
|
||||
* @since 2.4
|
||||
*
|
||||
* Based on JRegistryFormatINI::stringToObject
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
protected static function ini_to_array($data, $process_sections = false, $sections = array(), $filter = '')
|
||||
{
|
||||
// Check the memory cache for already processed strings.
|
||||
$hash = md5($data . ':' . (int) $process_sections . ':' . serialize($sections) . ':' . $filter);
|
||||
|
||||
if (isset(self::$cache[$hash])) {
|
||||
return self::$cache[$hash];
|
||||
}
|
||||
|
||||
// If no lines present just return the array.
|
||||
if (empty($data)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$array = array();
|
||||
$section = false;
|
||||
$lines = explode("\n", $data);
|
||||
|
||||
// Process the lines.
|
||||
foreach ($lines as $line) {
|
||||
// Trim any unnecessary whitespace.
|
||||
$line = trim($line);
|
||||
|
||||
// Ignore empty lines and comments.
|
||||
if (empty($line) || ($line[0] == ';')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($process_sections) {
|
||||
$length = strlen($line);
|
||||
|
||||
// If we are processing sections and the line is a section add the object and continue.
|
||||
if (($line[0] == '[') && ($line[$length - 1] == ']')) {
|
||||
$section = substr($line, 1, $length - 2);
|
||||
|
||||
// filter section by regular expression
|
||||
if ($filter) {
|
||||
if (preg_match('#' . $filter . '#', $section)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// allow all sections
|
||||
if (empty($sections)) {
|
||||
$array[$section] = array();
|
||||
} else {
|
||||
if (in_array($section, $sections)) {
|
||||
$array[$section] = array();
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
} elseif ($line[0] == '[') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check that an equal sign exists and is not the first character of the line.
|
||||
if (!strpos($line, '=')) {
|
||||
// Maybe throw exception?
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the key and value for the line.
|
||||
list($key, $value) = explode('=', $line, 2);
|
||||
|
||||
// Validate the key.
|
||||
if (preg_match('/[^A-Z0-9_]/i', $key)) {
|
||||
// Maybe throw exception?
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the value is quoted then we assume it is a string.
|
||||
$length = strlen($value);
|
||||
|
||||
if ($length && ($value[0] == '"') && ($value[$length - 1] == '"')) {
|
||||
// Strip the quotes and Convert the new line characters.
|
||||
$value = stripcslashes(substr($value, 1, ($length - 2)));
|
||||
$value = str_replace(array("\n", "\r"), array('\n', '\r'), $value);
|
||||
} else {
|
||||
// If the value is not quoted, we assume it is not a string.
|
||||
// If the value is 'false' assume boolean false.
|
||||
if ($value == 'false') {
|
||||
$value = false;
|
||||
}
|
||||
// If the value is 'true' assume boolean true.
|
||||
elseif ($value == 'true') {
|
||||
$value = true;
|
||||
}
|
||||
// If the value is numeric than it is either a float or int.
|
||||
elseif (is_numeric($value)) {
|
||||
// If there is a period then we assume a float.
|
||||
if (strpos($value, '.') !== false) {
|
||||
$value = (float) $value;
|
||||
} else {
|
||||
$value = (int) $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If a section is set add the key/value to the section, otherwise top level.
|
||||
if ($section) {
|
||||
$array[$section][$key] = $value;
|
||||
} else {
|
||||
$array[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
// Cache the string
|
||||
self::$cache[$hash] = $array;
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
protected static function getOverrides()
|
||||
{
|
||||
// get the language file
|
||||
$language = JFactory::getLanguage();
|
||||
// get language tag
|
||||
$tag = $language->getTag();
|
||||
|
||||
$file = JPATH_SITE . '/language/overrides/' . $tag . '.override.ini';
|
||||
|
||||
$ini = array();
|
||||
|
||||
if (is_file($file)) {
|
||||
$content = @file_get_contents($file);
|
||||
|
||||
if ($content && is_string($content)) {
|
||||
$ini = @parse_ini_string($content, true);
|
||||
}
|
||||
}
|
||||
|
||||
return $ini;
|
||||
}
|
||||
|
||||
protected static function filterSections($ini, $sections = array(), $filter = '')
|
||||
{
|
||||
if ($ini && is_array($ini)) {
|
||||
if (!empty($sections)) {
|
||||
$ini = array_intersect_key($ini, array_flip($sections));
|
||||
}
|
||||
|
||||
// filter keys by regular expression
|
||||
if ($filter) {
|
||||
foreach (array_keys($ini) as $key) {
|
||||
if (preg_match('#' . $filter . '#', $key)) {
|
||||
unset($ini[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ini;
|
||||
}
|
||||
|
||||
protected static function processLanguageINI($files, $sections = array(), $filter = '')
|
||||
{
|
||||
$data = array();
|
||||
|
||||
foreach ((array) $files as $file) {
|
||||
if (!is_file($file)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ini = false;
|
||||
|
||||
$content = @file_get_contents($file);
|
||||
|
||||
if ($content && is_string($content)) {
|
||||
if (function_exists('parse_ini_string')) {
|
||||
$ini = @parse_ini_string($content, true);
|
||||
// filter
|
||||
$ini = self::filterSections($ini, $sections, $filter);
|
||||
} else {
|
||||
$ini = self::ini_to_array($content, true, $sections, $filter);
|
||||
}
|
||||
}
|
||||
|
||||
// merge with data array
|
||||
if ($ini && is_array($ini)) {
|
||||
$data = array_merge($data, $ini);
|
||||
}
|
||||
}
|
||||
|
||||
$output = '';
|
||||
|
||||
// get overrides
|
||||
$overrides = self::getOverrides();
|
||||
|
||||
if (!empty($data)) {
|
||||
$x = 0;
|
||||
|
||||
foreach ($data as $key => $strings) {
|
||||
if (is_array($strings)) {
|
||||
$output .= '"' . strtolower($key) . '":{';
|
||||
|
||||
$i = 0;
|
||||
|
||||
foreach ($strings as $k => $v) {
|
||||
if (array_key_exists(strtoupper($k), $overrides)) {
|
||||
$v = $overrides[$k];
|
||||
}
|
||||
|
||||
// remove "
|
||||
$v = str_replace('"', '', $v);
|
||||
|
||||
if (is_numeric($v)) {
|
||||
$v = (float) $v;
|
||||
} else {
|
||||
$v = '"' . $v . '"';
|
||||
}
|
||||
|
||||
// key to lowercase
|
||||
$k = strtolower($k);
|
||||
|
||||
// remove WF_
|
||||
$k = str_replace('wf_', '', $k);
|
||||
|
||||
// remove "_dlg"
|
||||
$key = preg_replace('#_dlg$#', '', $key);
|
||||
|
||||
// remove the section name
|
||||
$k = preg_replace('#^' . $key . '(_dlg)?_#', '', $k);
|
||||
|
||||
// hex colours to uppercase and remove marker
|
||||
if (strpos($k, 'hex_') !== false) {
|
||||
$k = strtoupper(str_replace('hex_', '', $k));
|
||||
}
|
||||
|
||||
// create key/value pair as JSON string
|
||||
$output .= '"' . $k . '":' . $v . ',';
|
||||
|
||||
++$i;
|
||||
}
|
||||
// remove last comma
|
||||
$output = rtrim(trim($output), ',');
|
||||
|
||||
$output .= '},';
|
||||
|
||||
++$x;
|
||||
}
|
||||
}
|
||||
// remove last comma
|
||||
$output = rtrim(trim($output), ',');
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
private function getFilter()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function load($files = array())
|
||||
{
|
||||
// get language tag
|
||||
$tag = $this->language;
|
||||
|
||||
// base language path
|
||||
$path = JPATH_SITE . '/language/' . $tag;
|
||||
|
||||
// if no file set
|
||||
if (empty($files)) {
|
||||
// Add English language
|
||||
$files[] = JPATH_SITE . '/language/en-GB/en-GB.com_jce.ini';
|
||||
|
||||
// add pro language file
|
||||
$files[] = JPATH_SITE . '/language/en-GB/en-GB.com_jce_pro.ini';
|
||||
|
||||
// non-english language
|
||||
if ($tag != 'en-GB') {
|
||||
if (is_dir($path)) {
|
||||
$core = $path . '/' . $tag . '.com_jce.ini';
|
||||
$pro = $path . '/' . $tag . '.com_jce_pro.ini';
|
||||
|
||||
if (is_file($core)) {
|
||||
$files[] = $core;
|
||||
|
||||
if (is_file($pro)) {
|
||||
$files[] = $pro;
|
||||
}
|
||||
} else {
|
||||
$tag = 'en-GB';
|
||||
}
|
||||
} else {
|
||||
$tag = 'en-GB';
|
||||
}
|
||||
}
|
||||
|
||||
$plugins = $this->get('plugins');
|
||||
|
||||
if (!empty($plugins)) {
|
||||
foreach ($plugins['external'] as $name => $plugin) {
|
||||
// add English file
|
||||
$ini = JPATH_ADMINISTRATOR . '/language/en-GB/en-GB.plg_jce_editor_' . $name . '.ini';
|
||||
|
||||
if (is_file($ini)) {
|
||||
$files[] = $ini;
|
||||
}
|
||||
|
||||
// non-english language
|
||||
if ($tag != 'en-GB') {
|
||||
$ini = JPATH_ADMINISTRATOR . '/language/' . $tag . '/' . $tag . '.plg_jce_editor_' . $name . '.ini';
|
||||
|
||||
if (is_file($ini)) {
|
||||
$files[] = $ini;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// shorten the tag, eg: en-GB -> en
|
||||
$tag = substr($tag, 0, strpos($tag, '-'));
|
||||
|
||||
$sections = $this->get('sections');
|
||||
$filter = $this->getFilter();
|
||||
|
||||
$data = self::processLanguageINI($files, $sections, $filter);
|
||||
|
||||
// clean data
|
||||
$data = rtrim(trim($data), ',');
|
||||
|
||||
return 'tinyMCE.addI18n({"' . $tag . '":{' . $data . '}});';
|
||||
}
|
||||
|
||||
public function output($data)
|
||||
{
|
||||
if ($data) {
|
||||
ob_start();
|
||||
|
||||
header('Content-type: application/javascript; charset: UTF-8');
|
||||
header('Vary: Accept-Encoding');
|
||||
|
||||
// cache control
|
||||
header('Cache-Control: max-age=0,no-cache');
|
||||
|
||||
// get content hash
|
||||
$hash = md5($data);
|
||||
|
||||
// set etag header
|
||||
header('ETag: "' . $hash . '"');
|
||||
|
||||
echo $data;
|
||||
|
||||
exit(ob_get_clean());
|
||||
}
|
||||
exit();
|
||||
}
|
||||
}
|
||||
74
components/com_jce/editor/libraries/classes/linkhelper.php
Normal file
74
components/com_jce/editor/libraries/classes/linkhelper.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die('RESTRICTED');
|
||||
|
||||
abstract class WFLinkHelper
|
||||
{
|
||||
/**
|
||||
* Translates an internal Joomla URL to a humanly readible URL.
|
||||
*
|
||||
* @param string $url Absolute or Relative URI to Joomla resource
|
||||
*
|
||||
* @return The translated humanly readible URL
|
||||
*/
|
||||
public static function route($url)
|
||||
{
|
||||
$app = Joomla\CMS\Application\CMSApplication::getInstance('site');
|
||||
$router = $app->getRouter('site');
|
||||
|
||||
if (!$router) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
$uri = $router->build($url);
|
||||
$url = $uri->toString();
|
||||
$url = str_replace('/administrator/', '/', $url);
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
public static function removeItemId($url)
|
||||
{
|
||||
$url = preg_replace('#&Itemid=[0-9]+#', '', $url);
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
public static function removeHomeItemId($url) {
|
||||
if (strpos($url, 'Itemid') === false) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
$parsed = parse_url($url, PHP_URL_QUERY);
|
||||
$parsed = str_replace('&', '&', $parsed);
|
||||
|
||||
parse_str($parsed, $vars);
|
||||
|
||||
if (!array_key_exists('Itemid', $vars)) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
// get menus
|
||||
$menus = JFactory::getApplication()->getMenu('site');
|
||||
// get "default" menu
|
||||
$default = $menus->getDefault();
|
||||
|
||||
// Itemid is unique
|
||||
if ($default->id != $vars['Itemid']) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
// remove "default" Itemid
|
||||
$url = self::removeItemId($url);
|
||||
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
14
components/com_jce/editor/libraries/classes/manager.php
Normal file
14
components/com_jce/editor/libraries/classes/manager.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
if (is_dir(WF_EDITOR_LIBRARIES.'/pro')) {
|
||||
require_once WF_EDITOR_LIBRARIES.'/pro/classes/manager.php';
|
||||
} else {
|
||||
require_once __DIR__.'/manager/manager.php';
|
||||
}
|
||||
275
components/com_jce/editor/libraries/classes/manager/base.php
Normal file
275
components/com_jce/editor/libraries/classes/manager/base.php
Normal file
@@ -0,0 +1,275 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
class WFMediaManagerBase extends WFEditorPlugin
|
||||
{
|
||||
protected $_filetypes = 'jpg,jpeg,png,gif';
|
||||
|
||||
private static $browser = array();
|
||||
|
||||
public function __construct($config = array())
|
||||
{
|
||||
// use the full "manager" layout by default
|
||||
if (!array_key_exists('layout', $config)) {
|
||||
$config['layout'] = 'manager';
|
||||
}
|
||||
|
||||
if (!array_key_exists('view_path', $config)) {
|
||||
$config['view_path'] = WF_EDITOR_LIBRARIES . '/views/plugin';
|
||||
}
|
||||
|
||||
if (!array_key_exists('template_path', $config)) {
|
||||
$config['template_path'] = WF_EDITOR_LIBRARIES . '/views/plugin/tmpl';
|
||||
}
|
||||
|
||||
// Call parent
|
||||
parent::__construct($config);
|
||||
|
||||
// initialize the browser
|
||||
$browser = $this->getFileBrowser();
|
||||
$request = WFRequest::getInstance();
|
||||
|
||||
// Setup plugin XHR callback functions
|
||||
$request->setRequest(array($this, 'getDimensions'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the File Browser instance.
|
||||
*
|
||||
* @return object WFBrowserExtension
|
||||
*/
|
||||
public function getFileBrowser()
|
||||
{
|
||||
$name = $this->getName();
|
||||
$caller = $this->get('caller');
|
||||
|
||||
// add caller if set
|
||||
if ($caller) {
|
||||
$name .= '.' . $caller;
|
||||
}
|
||||
|
||||
if (!isset(self::$browser[$name])) {
|
||||
self::$browser[$name] = new WFFileBrowser($this->getFileBrowserConfig());
|
||||
}
|
||||
|
||||
return self::$browser[$name];
|
||||
}
|
||||
|
||||
protected function addFileBrowserAction($name, $options = array())
|
||||
{
|
||||
$this->getFileBrowser()->addAction($name, $options);
|
||||
}
|
||||
|
||||
protected function addFileBrowserButton($type, $name, $options = array())
|
||||
{
|
||||
$this->getFileBrowser()->addButton($type, $name, $options);
|
||||
}
|
||||
|
||||
protected function addFileBrowserEvent($name, $function = array())
|
||||
{
|
||||
$this->getFileBrowser()->addEvent($name, $function);
|
||||
}
|
||||
|
||||
public function getBrowser()
|
||||
{
|
||||
return $this->getFileBrowser();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the plugin.
|
||||
*/
|
||||
public function display()
|
||||
{
|
||||
parent::display();
|
||||
|
||||
$document = WFDocument::getInstance();
|
||||
|
||||
$view = $this->getView();
|
||||
$browser = $this->getFileBrowser();
|
||||
|
||||
$browser->display();
|
||||
$view->filebrowser = $browser;
|
||||
|
||||
$options = $browser->getProperties();
|
||||
|
||||
// process options array
|
||||
$browser->getFileSystem()->updateOptions($options);
|
||||
|
||||
// set global options
|
||||
$document->addScriptDeclaration('FileBrowser.options=' . json_encode($options) . ';');
|
||||
}
|
||||
|
||||
public function getFileTypes($format = 'array', $list = '')
|
||||
{
|
||||
return $this->getFileBrowser()->getFileTypes($format, $list);
|
||||
}
|
||||
|
||||
protected function setFileTypes($filetypes)
|
||||
{
|
||||
return $this->getFileBrowser()->setFileTypes($filetypes);
|
||||
}
|
||||
|
||||
private function getFileSystem()
|
||||
{
|
||||
$filesystem = $this->getParam('filesystem.name', '');
|
||||
|
||||
// if an object, get the name
|
||||
if (is_object($filesystem)) {
|
||||
$filesystem = isset($filesystem->name) ? $filesystem->name : 'joomla';
|
||||
}
|
||||
|
||||
// if no value, default to "joomla"
|
||||
if (empty($filesystem)) {
|
||||
$filesystem = 'joomla';
|
||||
}
|
||||
|
||||
return $filesystem;
|
||||
}
|
||||
|
||||
public function onUpload($file, $relative = '')
|
||||
{
|
||||
}
|
||||
|
||||
public function getDimensions($file)
|
||||
{
|
||||
$browser = $this->getFileBrowser();
|
||||
$filesystem = $browser->getFileSystem();
|
||||
|
||||
$path = WFUtility::makePath($filesystem->getBaseDir(), rawurldecode($file));
|
||||
|
||||
$data = array();
|
||||
|
||||
// images and flash
|
||||
if (preg_match('#\.(jpg|jpeg|png|apng|gif|bmp|wbmp|tif|tiff|psd|ico|webp|swf)$#i', $file)) {
|
||||
list($data['width'], $data['height']) = getimagesize($path);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
// svg
|
||||
if (preg_match('#\.svg$#i', $file)) {
|
||||
$svg = @simplexml_load_file($path);
|
||||
|
||||
if ($svg && isset($svg['viewBox'])) {
|
||||
list($start_x, $start_y, $end_x, $end_y) = explode(' ', $svg['viewBox']);
|
||||
|
||||
$width = (int) $end_x;
|
||||
$height = (int) $end_y;
|
||||
|
||||
if ($width && $height) {
|
||||
$data['width'] = $width;
|
||||
$data['height'] = $height;
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Media Manager configuration.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getFileBrowserConfig($config = array())
|
||||
{
|
||||
$filetypes = $this->getParam('extensions', $this->get('_filetypes'));
|
||||
$textcase = $this->getParam('editor.websafe_textcase', '');
|
||||
|
||||
// implode textcase array to create string
|
||||
if (is_array($textcase)) {
|
||||
$textcase = array_filter($textcase, 'strlen');
|
||||
$textcase = implode(',', $textcase);
|
||||
}
|
||||
|
||||
$filter = $this->getParam('editor.dir_filter', array());
|
||||
|
||||
// explode to array if string - 2.7.x...2.7.11
|
||||
if (!is_array($filter)) {
|
||||
$filter = explode(',', $filter);
|
||||
}
|
||||
|
||||
// remove empty values
|
||||
$filter = array_filter((array) $filter);
|
||||
|
||||
// get base directory from editor parameter
|
||||
$baseDir = $this->getParam('editor.dir', '', '', false);
|
||||
|
||||
// get directory from plugin parameter, fallback to base directory as it cannot itself be empty
|
||||
$dir = $this->getParam($this->getName() . '.dir', $baseDir);
|
||||
|
||||
// get websafe spaces parameter and convert legacy values
|
||||
$websafe_spaces = $this->getParam('editor.websafe_allow_spaces', '_');
|
||||
|
||||
if (is_numeric($websafe_spaces)) {
|
||||
// legacy replacement
|
||||
if ($websafe_spaces == 0) {
|
||||
$websafe_spaces = '_';
|
||||
}
|
||||
// convert to space
|
||||
if ($websafe_spaces == 1) {
|
||||
$websafe_spaces = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
// fix legacy list limit value
|
||||
$list_limit = $this->getParam('editor.list_limit', 0);
|
||||
|
||||
// convert "all" to 0
|
||||
if (!is_numeric($list_limit)) {
|
||||
$list_limit = 0;
|
||||
}
|
||||
|
||||
$base = array(
|
||||
'dir' => $dir,
|
||||
'filesystem' => $this->getFileSystem(),
|
||||
'filetypes' => $filetypes,
|
||||
'filter' => $filter,
|
||||
'upload' => array(
|
||||
'max_size' => $this->getParam('max_size', 1024),
|
||||
'validate_mimetype' => (int) $this->getParam('editor.validate_mimetype', 1),
|
||||
'add_random' => (int) $this->getParam('editor.upload_add_random', 0),
|
||||
'total_files' => (float) $this->getParam('editor.total_files', 0),
|
||||
'total_size' => (float) $this->getParam('editor.total_size', 0),
|
||||
'remove_exif' => (int) $this->getParam('editor.upload_remove_exif', 0),
|
||||
),
|
||||
'folder_tree' => $this->getParam('editor.folder_tree', 1),
|
||||
'list_limit' => $list_limit,
|
||||
'features' => array(
|
||||
'upload' => $this->getParam('upload', 1),
|
||||
'folder' => array(
|
||||
'create' => $this->getParam('folder_new', 1),
|
||||
'delete' => $this->getParam('folder_delete', 1),
|
||||
'rename' => $this->getParam('folder_rename', 1),
|
||||
'move' => $this->getParam('folder_move', 1),
|
||||
),
|
||||
'file' => array(
|
||||
'delete' => $this->getParam('file_delete', 1),
|
||||
'rename' => $this->getParam('file_rename', 1),
|
||||
'move' => $this->getParam('file_move', 1),
|
||||
),
|
||||
),
|
||||
'websafe_mode' => $this->getParam('editor.websafe_mode', 'utf-8'),
|
||||
'websafe_spaces' => $websafe_spaces,
|
||||
'websafe_textcase' => $textcase,
|
||||
'date_format' => $this->getParam('editor.date_format', '%d/%m/%Y, %H:%M'),
|
||||
'position' => $this->getParam('editor.filebrowser_position', $this->getParam('editor.browser_position', 'bottom')),
|
||||
'use_state_cookies' => $this->getParam('editor.use_cookies', true),
|
||||
'search_depth' => $this->getParam('editor.filebrowser_search_depth', 3),
|
||||
'allow_download' => $this->getParam('allow_download', 0)
|
||||
);
|
||||
|
||||
return WFUtility::array_merge_recursive_distinct($base, $config);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
class WFMediaManager extends WFMediaManagerBase
|
||||
{
|
||||
}
|
||||
744
components/com_jce/editor/libraries/classes/mime.php
Normal file
744
components/com_jce/editor/libraries/classes/mime.php
Normal file
@@ -0,0 +1,744 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
abstract class WFMimeType
|
||||
{
|
||||
/*
|
||||
* @var Array Mimetype values by extension
|
||||
* From mimetype list maintained at http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/conf/mime.types
|
||||
*/
|
||||
|
||||
private static $mimes = array(
|
||||
'application/andrew-inset' => 'ez',
|
||||
'application/applixware' => 'aw',
|
||||
'application/atom+xml' => 'atom',
|
||||
'application/atomcat+xml' => 'atomcat',
|
||||
'application/atomsvc+xml' => 'atomsvc',
|
||||
'application/ccxml+xml' => 'ccxml',
|
||||
'application/cu-seeme' => 'cu',
|
||||
'application/davmount+xml' => 'davmount',
|
||||
'application/dssc+der' => 'dssc',
|
||||
'application/dssc+xml' => 'xdssc',
|
||||
'application/ecmascript' => 'ecma',
|
||||
'application/emma+xml' => 'emma',
|
||||
'application/epub+zip' => 'epub',
|
||||
'application/font-tdpfr' => 'pfr',
|
||||
'application/hyperstudio' => 'stk',
|
||||
'application/ipfix' => 'ipfix',
|
||||
'application/java-archive' => 'jar',
|
||||
'application/java-serialized-object' => 'ser',
|
||||
'application/java-vm' => 'class',
|
||||
'application/javascript' => 'js',
|
||||
'application/json' => 'json',
|
||||
'application/lost+xml' => 'lostxml',
|
||||
'application/mac-binhex40' => 'hqx',
|
||||
'application/mac-compactpro' => 'cpt',
|
||||
'application/marc' => 'mrc',
|
||||
'application/mathematica' => 'ma nb mb',
|
||||
'application/mathml+xml' => 'mathml',
|
||||
'application/mbox' => 'mbox',
|
||||
'application/mediaservercontrol+xml' => 'mscml',
|
||||
'application/mp4' => 'mp4s',
|
||||
'application/msword' => 'doc dot ppt xls xlsm dotx docx pptx xlsx ppsx sldx potx xltx',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => 'dotx',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'ppsx',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.slide' => 'sldx',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.template' => 'potx',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => 'xltx',
|
||||
'application/mxf' => 'mxf',
|
||||
'application/octet-stream' => 'bin dms lha lrf lzh so iso dmg dist distz pkg bpk dump elc deploy',
|
||||
'application/oda' => 'oda',
|
||||
'application/oebps-package+xml' => 'opf',
|
||||
'application/ogg' => 'ogx ogg ogv oga',
|
||||
'application/onenote' => 'onetoc onetoc2 onetmp onepkg',
|
||||
'application/patch-ops-error+xml' => 'xer',
|
||||
'application/pdf' => 'pdf',
|
||||
'application/pgp-encrypted' => 'pgp',
|
||||
'application/pgp-signature' => 'asc sig',
|
||||
'application/pics-rules' => 'prf',
|
||||
'application/pkcs10' => 'p10',
|
||||
'application/pkcs7-mime' => 'p7m p7c',
|
||||
'application/pkcs7-signature' => 'p7s',
|
||||
'application/pkix-cert' => 'cer',
|
||||
'application/pkix-crl' => 'crl',
|
||||
'application/pkix-pkipath' => 'pkipath',
|
||||
'application/pkixcmp' => 'pki',
|
||||
'application/pls+xml' => 'pls',
|
||||
'application/postscript' => 'ai eps ps',
|
||||
'application/prs.cww' => 'cww',
|
||||
'application/rdf+xml' => 'rdf',
|
||||
'application/reginfo+xml' => 'rif',
|
||||
'application/relax-ng-compact-syntax' => 'rnc',
|
||||
'application/resource-lists+xml' => 'rl',
|
||||
'application/resource-lists-diff+xml' => 'rld',
|
||||
'application/rls-services+xml' => 'rs',
|
||||
'application/rsd+xml' => 'rsd',
|
||||
'application/rss+xml' => 'rss',
|
||||
'application/rtf' => 'rtf',
|
||||
'application/sbml+xml' => 'sbml',
|
||||
'application/scvp-cv-request' => 'scq',
|
||||
'application/scvp-cv-response' => 'scs',
|
||||
'application/scvp-vp-request' => 'spq',
|
||||
'application/scvp-vp-response' => 'spp',
|
||||
'application/sdp' => 'sdp',
|
||||
'application/set-payment-initiation' => 'setpay',
|
||||
'application/set-registration-initiation' => 'setreg',
|
||||
'application/shf+xml' => 'shf',
|
||||
'application/smil+xml' => 'smi smil',
|
||||
'application/sparql-query' => 'rq',
|
||||
'application/sparql-results+xml' => 'srx',
|
||||
'application/srgs' => 'gram',
|
||||
'application/srgs+xml' => 'grxml',
|
||||
'application/ssml+xml' => 'ssml',
|
||||
'application/vnd.3gpp.pic-bw-large' => 'plb',
|
||||
'application/vnd.3gpp.pic-bw-small' => 'psb',
|
||||
'application/vnd.3gpp.pic-bw-var' => 'pvb',
|
||||
'application/vnd.3gpp2.tcap' => 'tcap',
|
||||
'application/vnd.3m.post-it-notes' => 'pwn',
|
||||
'application/vnd.accpac.simply.aso' => 'aso',
|
||||
'application/vnd.accpac.simply.imp' => 'imp',
|
||||
'application/vnd.acucobol' => 'acu',
|
||||
'application/vnd.acucorp' => 'atc acutc',
|
||||
'application/vnd.adobe.air-application-installer-package+zip' => 'air',
|
||||
'application/vnd.adobe.xdp+xml' => 'xdp',
|
||||
'application/vnd.adobe.xfdf' => 'xfdf',
|
||||
'application/vnd.airzip.filesecure.azf' => 'azf',
|
||||
'application/vnd.airzip.filesecure.azs' => 'azs',
|
||||
'application/vnd.amazon.ebook' => 'azw',
|
||||
'application/vnd.americandynamics.acc' => 'acc',
|
||||
'application/vnd.amiga.ami' => 'ami',
|
||||
'application/vnd.android.package-archive' => 'apk',
|
||||
'application/vnd.anser-web-certificate-issue-initiation' => 'cii',
|
||||
'application/vnd.anser-web-funds-transfer-initiation' => 'fti',
|
||||
'application/vnd.antix.game-component' => 'atx',
|
||||
'application/vnd.apple.installer+xml' => 'mpkg',
|
||||
'application/vnd.apple.mpegurl' => 'm3u8',
|
||||
'application/vnd.aristanetworks.swi' => 'swi',
|
||||
'application/vnd.audiograph' => 'aep',
|
||||
'application/vnd.blueice.multipass' => 'mpm',
|
||||
'application/vnd.bmi' => 'bmi',
|
||||
'application/vnd.businessobjects' => 'rep',
|
||||
'application/vnd.chemdraw+xml' => 'cdxml',
|
||||
'application/vnd.chipnuts.karaoke-mmd' => 'mmd',
|
||||
'application/vnd.cinderella' => 'cdy',
|
||||
'application/vnd.claymore' => 'cla',
|
||||
'application/vnd.cloanto.rp9' => 'rp9',
|
||||
'application/vnd.clonk.c4group' => 'c4g c4d c4f c4p c4u',
|
||||
'application/vnd.commonspace' => 'csp',
|
||||
'application/vnd.contact.cmsg' => 'cdbcmsg',
|
||||
'application/vnd.cosmocaller' => 'cmc',
|
||||
'application/vnd.crick.clicker' => 'clkx',
|
||||
'application/vnd.crick.clicker.keyboard' => 'clkk',
|
||||
'application/vnd.crick.clicker.palette' => 'clkp',
|
||||
'application/vnd.crick.clicker.template' => 'clkt',
|
||||
'application/vnd.crick.clicker.wordbank' => 'clkw',
|
||||
'application/vnd.criticaltools.wbs+xml' => 'wbs',
|
||||
'application/vnd.ctc-posml' => 'pml',
|
||||
'application/vnd.cups-ppd' => 'ppd',
|
||||
'application/vnd.curl.car' => 'car',
|
||||
'application/vnd.curl.pcurl' => 'pcurl',
|
||||
'application/vnd.data-vision.rdz' => 'rdz',
|
||||
'application/vnd.denovo.fcselayout-link' => 'fe_launch',
|
||||
'application/vnd.dna' => 'dna',
|
||||
'application/vnd.dolby.mlp' => 'mlp',
|
||||
'application/vnd.dpgraph' => 'dpg',
|
||||
'application/vnd.dreamfactory' => 'dfac',
|
||||
'application/vnd.dynageo' => 'geo',
|
||||
'application/vnd.ecowin.chart' => 'mag',
|
||||
'application/vnd.enliven' => 'nml',
|
||||
'application/vnd.epson.esf' => 'esf',
|
||||
'application/vnd.epson.msf' => 'msf',
|
||||
'application/vnd.epson.quickanime' => 'qam',
|
||||
'application/vnd.epson.salt' => 'slt',
|
||||
'application/vnd.epson.ssf' => 'ssf',
|
||||
'application/vnd.eszigno3+xml' => 'es3 et3',
|
||||
'application/vnd.ezpix-album' => 'ez2',
|
||||
'application/vnd.ezpix-package' => 'ez3',
|
||||
'application/vnd.fdf' => 'fdf',
|
||||
'application/vnd.fdsn.mseed' => 'mseed',
|
||||
'application/vnd.fdsn.seed' => 'seed dataless',
|
||||
'application/vnd.flographit' => 'gph',
|
||||
'application/vnd.fluxtime.clip' => 'ftc',
|
||||
'application/vnd.framemaker' => 'fm frame maker book',
|
||||
'application/vnd.frogans.fnc' => 'fnc',
|
||||
'application/vnd.frogans.ltf' => 'ltf',
|
||||
'application/vnd.fsc.weblaunch' => 'fsc',
|
||||
'application/vnd.fujitsu.oasys' => 'oas',
|
||||
'application/vnd.fujitsu.oasys2' => 'oa2',
|
||||
'application/vnd.fujitsu.oasys3' => 'oa3',
|
||||
'application/vnd.fujitsu.oasysgp' => 'fg5',
|
||||
'application/vnd.fujitsu.oasysprs' => 'bh2',
|
||||
'application/vnd.fujixerox.ddd' => 'ddd',
|
||||
'application/vnd.fujixerox.docuworks' => 'xdw',
|
||||
'application/vnd.fujixerox.docuworks.binder' => 'xbd',
|
||||
'application/vnd.fuzzysheet' => 'fzs',
|
||||
'application/vnd.genomatix.tuxedo' => 'txd',
|
||||
'application/vnd.geogebra.file' => 'ggb',
|
||||
'application/vnd.geogebra.tool' => 'ggt',
|
||||
'application/vnd.geometry-explorer' => 'gex gre',
|
||||
'application/vnd.geonext' => 'gxt',
|
||||
'application/vnd.geoplan' => 'g2w',
|
||||
'application/vnd.geospace' => 'g3w',
|
||||
'application/vnd.gmx' => 'gmx',
|
||||
'application/vnd.google-earth.kml+xml' => 'kml',
|
||||
'application/vnd.google-earth.kmz' => 'kmz',
|
||||
'application/vnd.grafeq' => 'gqf gqs',
|
||||
'application/vnd.groove-account' => 'gac',
|
||||
'application/vnd.groove-help' => 'ghf',
|
||||
'application/vnd.groove-identity-message' => 'gim',
|
||||
'application/vnd.groove-injector' => 'grv',
|
||||
'application/vnd.groove-tool-message' => 'gtm',
|
||||
'application/vnd.groove-tool-template' => 'tpl',
|
||||
'application/vnd.groove-vcard' => 'vcg',
|
||||
'application/vnd.handheld-entertainment+xml' => 'zmm',
|
||||
'application/vnd.hbci' => 'hbci',
|
||||
'application/vnd.hhe.lesson-player' => 'les',
|
||||
'application/vnd.hp-hpgl' => 'hpgl',
|
||||
'application/vnd.hp-hpid' => 'hpid',
|
||||
'application/vnd.hp-hps' => 'hps',
|
||||
'application/vnd.hp-jlyt' => 'jlt',
|
||||
'application/vnd.hp-pcl' => 'pcl',
|
||||
'application/vnd.hp-pclxl' => 'pclxl',
|
||||
'application/vnd.hydrostatix.sof-data' => 'sfd-hdstx',
|
||||
'application/vnd.hzn-3d-crossword' => 'x3d',
|
||||
'application/vnd.ibm.minipay' => 'mpy',
|
||||
'application/vnd.ibm.modcap' => 'afp listafp list3820',
|
||||
'application/vnd.ibm.rights-management' => 'irm',
|
||||
'application/vnd.ibm.secure-container' => 'sc',
|
||||
'application/vnd.iccprofile' => 'icc icm',
|
||||
'application/vnd.igloader' => 'igl',
|
||||
'application/vnd.immervision-ivp' => 'ivp',
|
||||
'application/vnd.immervision-ivu' => 'ivu',
|
||||
'application/vnd.intercon.formnet' => 'xpw xpx',
|
||||
'application/vnd.intu.qbo' => 'qbo',
|
||||
'application/vnd.intu.qfx' => 'qfx',
|
||||
'application/vnd.ipunplugged.rcprofile' => 'rcprofile',
|
||||
'application/vnd.irepository.package+xml' => 'irp',
|
||||
'application/vnd.is-xpr' => 'xpr',
|
||||
'application/vnd.jam' => 'jam',
|
||||
'application/vnd.jcp.javame.midlet-rms' => 'rms',
|
||||
'application/vnd.jisp' => 'jisp',
|
||||
'application/vnd.joost.joda-archive' => 'joda',
|
||||
'application/vnd.kahootz' => 'ktz ktr',
|
||||
'application/vnd.kde.karbon' => 'karbon',
|
||||
'application/vnd.kde.kchart' => 'chrt',
|
||||
'application/vnd.kde.kformula' => 'kfo',
|
||||
'application/vnd.kde.kivio' => 'flw',
|
||||
'application/vnd.kde.kontour' => 'kon',
|
||||
'application/vnd.kde.kpresenter' => 'kpr kpt',
|
||||
'application/vnd.kde.kspread' => 'ksp',
|
||||
'application/vnd.kde.kword' => 'kwd kwt',
|
||||
'application/vnd.kenameaapp' => 'htke',
|
||||
'application/vnd.kidspiration' => 'kia',
|
||||
'application/vnd.kinar' => 'kne knp',
|
||||
'application/vnd.koan' => 'skp skd skt skm',
|
||||
'application/vnd.kodak-descriptor' => 'sse',
|
||||
'application/vnd.llamagraphics.life-balance.desktop' => 'lbd',
|
||||
'application/vnd.llamagraphics.life-balance.exchange+xml' => 'lbe',
|
||||
'application/vnd.lotus-1-2-3' => '123',
|
||||
'application/vnd.lotus-approach' => 'apr',
|
||||
'application/vnd.lotus-freelance' => 'pre',
|
||||
'application/vnd.lotus-notes' => 'nsf',
|
||||
'application/vnd.lotus-organizer' => 'org',
|
||||
'application/vnd.lotus-screencam' => 'scm',
|
||||
'application/vnd.lotus-wordpro' => 'lwp',
|
||||
'application/vnd.macports.portpkg' => 'portpkg',
|
||||
'application/vnd.mcd' => 'mcd',
|
||||
'application/vnd.medcalcdata' => 'mc1',
|
||||
'application/vnd.mediastation.cdkey' => 'cdkey',
|
||||
'application/vnd.mfer' => 'mwf',
|
||||
'application/vnd.mfmp' => 'mfm',
|
||||
'application/vnd.micrografx.flo' => 'flo',
|
||||
'application/vnd.micrografx.igx' => 'igx',
|
||||
'application/vnd.mif' => 'mif',
|
||||
'application/vnd.mobius.daf' => 'daf',
|
||||
'application/vnd.mobius.dis' => 'dis',
|
||||
'application/vnd.mobius.mbk' => 'mbk',
|
||||
'application/vnd.mobius.mqy' => 'mqy',
|
||||
'application/vnd.mobius.msl' => 'msl',
|
||||
'application/vnd.mobius.plc' => 'plc',
|
||||
'application/vnd.mobius.txf' => 'txf',
|
||||
'application/vnd.mophun.application' => 'mpn',
|
||||
'application/vnd.mophun.certificate' => 'mpc',
|
||||
'application/vnd.mozilla.xul+xml' => 'xul',
|
||||
'application/vnd.ms-artgalry' => 'cil',
|
||||
'application/vnd.ms-cab-compressed' => 'cab',
|
||||
'application/vnd.ms-excel' => 'xls xlm xla xlc xlt xlw xlsx xlsm',
|
||||
'application/vnd.ms-excel.addin.macroenabled.12' => 'xlam',
|
||||
'application/vnd.ms-excel.sheet.binary.macroenabled.12' => 'xlsb',
|
||||
'application/vnd.ms-excel.sheet.macroenabled.12' => 'xlsm',
|
||||
'application/vnd.ms-excel.template.macroenabled.12' => 'xltm',
|
||||
'application/vnd.ms-fontobject' => 'eot',
|
||||
'application/vnd.ms-htmlhelp' => 'chm',
|
||||
'application/vnd.ms-ims' => 'ims',
|
||||
'application/vnd.ms-lrm' => 'lrm',
|
||||
'application/vnd.ms-pki.seccat' => 'cat',
|
||||
'application/vnd.ms-pki.stl' => 'stl',
|
||||
'application/vnd.ms-powerpoint' => 'ppt pps pot pptx',
|
||||
'application/vnd.ms-powerpoint.addin.macroenabled.12' => 'ppam',
|
||||
'application/vnd.ms-powerpoint.presentation.macroenabled.12' => 'pptm',
|
||||
'application/vnd.ms-powerpoint.slide.macroenabled.12' => 'sldm',
|
||||
'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => 'ppsm',
|
||||
'application/vnd.ms-powerpoint.template.macroenabled.12' => 'potm',
|
||||
'application/vnd.ms-project' => 'mpp mpt',
|
||||
'application/vnd.ms-word.document.macroenabled.12' => 'docm',
|
||||
'application/vnd.ms-word.template.macroenabled.12' => 'dotm',
|
||||
'application/vnd.ms-works' => 'wps wks wcm wdb',
|
||||
'application/vnd.ms-wpl' => 'wpl',
|
||||
'application/vnd.ms-xpsdocument' => 'xps',
|
||||
'application/vnd.mseq' => 'mseq',
|
||||
'application/vnd.musician' => 'mus',
|
||||
'application/vnd.muvee.style' => 'msty',
|
||||
'application/vnd.neurolanguage.nlu' => 'nlu',
|
||||
'application/vnd.noblenet-directory' => 'nnd',
|
||||
'application/vnd.noblenet-sealer' => 'nns',
|
||||
'application/vnd.noblenet-web' => 'nnw',
|
||||
'application/vnd.nokia.n-gage.data' => 'ngdat',
|
||||
'application/vnd.nokia.n-gage.symbian.install' => 'n-gage',
|
||||
'application/vnd.nokia.radio-preset' => 'rpst',
|
||||
'application/vnd.nokia.radio-presets' => 'rpss',
|
||||
'application/vnd.novadigm.edm' => 'edm',
|
||||
'application/vnd.novadigm.edx' => 'edx',
|
||||
'application/vnd.novadigm.ext' => 'ext',
|
||||
'application/vnd.oasis.opendocument.chart' => 'odc',
|
||||
'application/vnd.oasis.opendocument.chart-template' => 'otc',
|
||||
'application/vnd.oasis.opendocument.database' => 'odb',
|
||||
'application/vnd.oasis.opendocument.formula' => 'odf',
|
||||
'application/vnd.oasis.opendocument.formula-template' => 'odft',
|
||||
'application/vnd.oasis.opendocument.graphics' => 'odg',
|
||||
'application/vnd.oasis.opendocument.graphics-template' => 'otg',
|
||||
'application/vnd.oasis.opendocument.image' => 'odi',
|
||||
'application/vnd.oasis.opendocument.image-template' => 'oti',
|
||||
'application/vnd.oasis.opendocument.presentation' => 'odp',
|
||||
'application/vnd.oasis.opendocument.presentation-template' => 'otp',
|
||||
'application/vnd.oasis.opendocument.spreadsheet' => 'ods',
|
||||
'application/vnd.oasis.opendocument.spreadsheet-template' => 'ots',
|
||||
'application/vnd.oasis.opendocument.text' => 'odt',
|
||||
'application/vnd.oasis.opendocument.text-master' => 'otm',
|
||||
'application/vnd.oasis.opendocument.text-template' => 'ott',
|
||||
'application/vnd.oasis.opendocument.text-web' => 'oth',
|
||||
'application/vnd.olpc-sugar' => 'xo',
|
||||
'application/vnd.oma.dd2+xml' => 'dd2',
|
||||
'application/vnd.openofficeorg.extension' => 'oxt',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'pptx',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.slide' => 'sldx',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'ppsx',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.template' => 'potx',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'xlsx',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => 'xltx',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'docx dotx',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => 'dotx',
|
||||
'application/vnd.osgi.dp' => 'dp',
|
||||
'application/vnd.palm' => 'pdb pqa oprc',
|
||||
'application/vnd.pawaafile' => 'paw',
|
||||
'application/vnd.pg.format' => 'str',
|
||||
'application/vnd.pg.osasli' => 'ei6',
|
||||
'application/vnd.picsel' => 'efif',
|
||||
'application/vnd.pmi.widget' => 'wg',
|
||||
'application/vnd.pocketlearn' => 'plf',
|
||||
'application/vnd.powerbuilder6' => 'pbd',
|
||||
'application/vnd.previewsystems.box' => 'box',
|
||||
'application/vnd.proteus.magazine' => 'mgz',
|
||||
'application/vnd.publishare-delta-tree' => 'qps',
|
||||
'application/vnd.pvi.ptid1' => 'ptid',
|
||||
'application/vnd.quark.quarkxpress' => 'qxd qxt qwd qwt qxl qxb',
|
||||
'application/vnd.realvnc.bed' => 'bed',
|
||||
'application/vnd.recordare.musicxml' => 'mxl',
|
||||
'application/vnd.recordare.musicxml+xml' => 'musicxml',
|
||||
'application/vnd.rim.cod' => 'cod',
|
||||
'application/vnd.rn-realmedia' => 'rm',
|
||||
'application/vnd.route66.link66+xml' => 'link66',
|
||||
'application/vnd.sailingtracker.track' => 'st',
|
||||
'application/vnd.seemail' => 'see',
|
||||
'application/vnd.sema' => 'sema',
|
||||
'application/vnd.semd' => 'semd',
|
||||
'application/vnd.semf' => 'semf',
|
||||
'application/vnd.shana.informed.formdata' => 'ifm',
|
||||
'application/vnd.shana.informed.formtemplate' => 'itp',
|
||||
'application/vnd.shana.informed.interchange' => 'iif',
|
||||
'application/vnd.shana.informed.package' => 'ipk',
|
||||
'application/vnd.simtech-mindmapper' => 'twd twds',
|
||||
'application/vnd.smaf' => 'mmf',
|
||||
'application/vnd.smart.teacher' => 'teacher',
|
||||
'application/vnd.solent.sdkm+xml' => 'sdkm sdkd',
|
||||
'application/vnd.spotfire.dxp' => 'dxp',
|
||||
'application/vnd.spotfire.sfs' => 'sfs',
|
||||
'application/vnd.stardivision.calc' => 'sdc',
|
||||
'application/vnd.stardivision.draw' => 'sda',
|
||||
'application/vnd.stardivision.impress' => 'sdd',
|
||||
'application/vnd.stardivision.math' => 'smf',
|
||||
'application/vnd.stardivision.writer' => 'sdw vor',
|
||||
'application/vnd.stardivision.writer-global' => 'sgl',
|
||||
'application/vnd.sun.xml.calc' => 'sxc',
|
||||
'application/vnd.sun.xml.calc.template' => 'stc',
|
||||
'application/vnd.sun.xml.draw' => 'sxd',
|
||||
'application/vnd.sun.xml.draw.template' => 'std',
|
||||
'application/vnd.sun.xml.impress' => 'sxi',
|
||||
'application/vnd.sun.xml.impress.template' => 'sti',
|
||||
'application/vnd.sun.xml.math' => 'sxm',
|
||||
'application/vnd.sun.xml.writer' => 'sxw',
|
||||
'application/vnd.sun.xml.writer.global' => 'sxg',
|
||||
'application/vnd.sun.xml.writer.template' => 'stw',
|
||||
'application/vnd.sus-calendar' => 'sus susp',
|
||||
'application/vnd.svd' => 'svd',
|
||||
'application/vnd.symbian.install' => 'sis sisx',
|
||||
'application/vnd.syncml+xml' => 'xsm',
|
||||
'application/vnd.syncml.dm+wbxml' => 'bdm',
|
||||
'application/vnd.syncml.dm+xml' => 'xdm',
|
||||
'application/vnd.tao.intent-module-archive' => 'tao',
|
||||
'application/vnd.tmobile-livetv' => 'tmo',
|
||||
'application/vnd.trid.tpt' => 'tpt',
|
||||
'application/vnd.triscape.mxs' => 'mxs',
|
||||
'application/vnd.trueapp' => 'tra',
|
||||
'application/vnd.ufdl' => 'ufd ufdl',
|
||||
'application/vnd.uiq.theme' => 'utz',
|
||||
'application/vnd.umajin' => 'umj',
|
||||
'application/vnd.unity' => 'unityweb',
|
||||
'application/vnd.uoml+xml' => 'uoml',
|
||||
'application/vnd.vcx' => 'vcx',
|
||||
'application/vnd.visio' => 'vsd vst vss vsw',
|
||||
'application/vnd.visionary' => 'vis',
|
||||
'application/vnd.vsf' => 'vsf',
|
||||
'application/vnd.wap.wbxml' => 'wbxml',
|
||||
'application/vnd.wap.wmlc' => 'wmlc',
|
||||
'application/vnd.wap.wmlscriptc' => 'wmlsc',
|
||||
'application/vnd.webturbo' => 'wtb',
|
||||
'application/vnd.wolfram.player' => 'nbp',
|
||||
'application/vnd.wordperfect' => 'wpd',
|
||||
'application/vnd.wqd' => 'wqd',
|
||||
'application/vnd.wt.stf' => 'stf',
|
||||
'application/vnd.xara' => 'xar',
|
||||
'application/vnd.xfdl' => 'xfdl',
|
||||
'application/vnd.yamaha.hv-dic' => 'hvd',
|
||||
'application/vnd.yamaha.hv-script' => 'hvs',
|
||||
'application/vnd.yamaha.hv-voice' => 'hvp',
|
||||
'application/vnd.yamaha.openscoreformat' => 'osf',
|
||||
'application/vnd.yamaha.openscoreformat.osfpvg+xml' => 'osfpvg',
|
||||
'application/vnd.yamaha.smaf-audio' => 'saf',
|
||||
'application/vnd.yamaha.smaf-phrase' => 'spf',
|
||||
'application/vnd.yellowriver-custom-menu' => 'cmp',
|
||||
'application/vnd.zul' => 'zir zirz',
|
||||
'application/vnd.zzazz.deck+xml' => 'zaz',
|
||||
'application/voicexml+xml' => 'vxml',
|
||||
'application/winhlp' => 'hlp',
|
||||
'application/wsdl+xml' => 'wsdl',
|
||||
'application/wspolicy+xml' => 'wspolicy',
|
||||
'application/x-abiword' => 'abw',
|
||||
'application/x-ace-compressed' => 'ace',
|
||||
'application/x-authorware-bin' => 'aab x32 u32 vox',
|
||||
'application/x-authorware-map' => 'aam',
|
||||
'application/x-authorware-seg' => 'aas',
|
||||
'application/x-bcpio' => 'bcpio',
|
||||
'application/x-bittorrent' => 'torrent',
|
||||
'application/x-bzip' => 'bz',
|
||||
'application/x-bzip2' => 'bz2 boz',
|
||||
'application/x-cdlink' => 'vcd',
|
||||
'application/x-chat' => 'chat',
|
||||
'application/x-chess-pgn' => 'pgn',
|
||||
'application/x-cpio' => 'cpio',
|
||||
'application/x-csh' => 'csh',
|
||||
'application/x-debian-package' => 'deb udeb',
|
||||
'application/x-director' => 'dir dcr dxr cst cct cxt w3d fgd swa',
|
||||
'application/x-doom' => 'wad',
|
||||
'application/x-dtbncx+xml' => 'ncx',
|
||||
'application/x-dtbook+xml' => 'dtb',
|
||||
'application/x-dtbresource+xml' => 'res',
|
||||
'application/x-dvi' => 'dvi',
|
||||
'application/x-font-bdf' => 'bdf',
|
||||
'application/x-font-ghostscript' => 'gsf',
|
||||
'application/x-font-linux-psf' => 'psf',
|
||||
'application/x-font-otf' => 'otf',
|
||||
'application/x-font-pcf' => 'pcf',
|
||||
'application/x-font-snf' => 'snf',
|
||||
'application/x-font-ttf' => 'ttf ttc',
|
||||
'application/x-font-type1' => 'pfa pfb pfm afm',
|
||||
'application/x-futuresplash' => 'spl',
|
||||
'application/x-gnumeric' => 'gnumeric',
|
||||
'application/x-gtar' => 'gtar',
|
||||
'application/x-hdf' => 'hdf',
|
||||
'application/x-java-jnlp-file' => 'jnlp',
|
||||
'application/x-latex' => 'latex',
|
||||
'application/x-mobipocket-ebook' => 'prc mobi',
|
||||
'application/x-ms-application' => 'application',
|
||||
'application/x-ms-wmd' => 'wmd',
|
||||
'application/x-ms-wmz' => 'wmz',
|
||||
'application/x-ms-xbap' => 'xbap',
|
||||
'application/x-msaccess' => 'mdb',
|
||||
'application/x-msbinder' => 'obd',
|
||||
'application/x-mscardfile' => 'crd',
|
||||
'application/x-msclip' => 'clp',
|
||||
'application/x-msdownload' => 'exe dll com bat msi',
|
||||
'application/x-msmediaview' => 'mvb m13 m14',
|
||||
'application/x-msmetafile' => 'wmf',
|
||||
'application/x-msmoney' => 'mny',
|
||||
'application/x-mspublisher' => 'pub',
|
||||
'application/x-msschedule' => 'scd',
|
||||
'application/x-msterminal' => 'trm',
|
||||
'application/x-mswrite' => 'wri',
|
||||
'application/x-netcdf' => 'nc cdf',
|
||||
'application/x-pkcs12' => 'p12 pfx',
|
||||
'application/x-pkcs7-certificates' => 'p7b spc',
|
||||
'application/x-pkcs7-certreqresp' => 'p7r',
|
||||
'application/x-rar-compressed' => 'rar',
|
||||
'application/x-sh' => 'sh',
|
||||
'application/x-shar' => 'shar',
|
||||
'application/x-shockwave-flash' => 'swf',
|
||||
'application/x-silverlight-app' => 'xap',
|
||||
'application/x-stuffit' => 'sit',
|
||||
'application/x-stuffitx' => 'sitx',
|
||||
'application/x-sv4cpio' => 'sv4cpio',
|
||||
'application/x-sv4crc' => 'sv4crc',
|
||||
'application/x-tar' => 'tar',
|
||||
'application/x-tcl' => 'tcl',
|
||||
'application/x-tex' => 'tex',
|
||||
'application/x-tex-tfm' => 'tfm',
|
||||
'application/x-texinfo' => 'texinfo texi',
|
||||
'application/x-ustar' => 'ustar',
|
||||
'application/x-wais-source' => 'src',
|
||||
'application/x-x509-ca-cert' => 'der crt',
|
||||
'application/x-xfig' => 'fig',
|
||||
'application/x-xpinstall' => 'xpi',
|
||||
'application/xenc+xml' => 'xenc',
|
||||
'application/xhtml+xml' => 'xhtml xht',
|
||||
'application/xml' => 'xml xsl',
|
||||
'application/xml-dtd' => 'dtd',
|
||||
'application/xop+xml' => 'xop',
|
||||
'application/xslt+xml' => 'xslt',
|
||||
'application/xspf+xml' => 'xspf',
|
||||
'application/xv+xml' => 'mxml xhvml xvml xvm',
|
||||
'application/zip' => 'zip docx pptx ppsx xlsx sldx potx xltx dotx',
|
||||
'audio/adpcm' => 'adp',
|
||||
'audio/basic' => 'au snd',
|
||||
'audio/midi' => 'mid midi kar rmi',
|
||||
'audio/mp4' => 'mp4a',
|
||||
'audio/mpeg' => 'mpga mp2 mp2a mp3 m2a m3a',
|
||||
'audio/ogg' => 'oga ogg spx',
|
||||
'audio/vnd.digital-winds' => 'eol',
|
||||
'audio/vnd.dra' => 'dra',
|
||||
'audio/vnd.dts' => 'dts',
|
||||
'audio/vnd.dts.hd' => 'dtshd',
|
||||
'audio/vnd.lucent.voice' => 'lvp',
|
||||
'audio/vnd.ms-playready.media.pya' => 'pya',
|
||||
'audio/vnd.nuera.ecelp4800' => 'ecelp4800',
|
||||
'audio/vnd.nuera.ecelp7470' => 'ecelp7470',
|
||||
'audio/vnd.nuera.ecelp9600' => 'ecelp9600',
|
||||
'audio/x-aac' => 'aac',
|
||||
'audio/x-aiff' => 'aif aiff aifc',
|
||||
'audio/x-mpegurl' => 'm3u',
|
||||
'audio/x-ms-wax' => 'wax',
|
||||
'audio/x-ms-wma' => 'wma',
|
||||
'audio/x-pn-realaudio' => 'ram ra',
|
||||
'audio/x-pn-realaudio-plugin' => 'rmp',
|
||||
'audio/x-wav' => 'wav',
|
||||
'audio/webm' => 'webm',
|
||||
'chemical/x-cdx' => 'cdx',
|
||||
'chemical/x-cif' => 'cif',
|
||||
'chemical/x-cmdf' => 'cmdf',
|
||||
'chemical/x-cml' => 'cml',
|
||||
'chemical/x-csml' => 'csml',
|
||||
'chemical/x-xyz' => 'xyz',
|
||||
'image/bmp' => 'bmp',
|
||||
'image/cgm' => 'cgm',
|
||||
'image/g3fax' => 'g3',
|
||||
'image/gif' => 'gif',
|
||||
'image/ief' => 'ief',
|
||||
'image/jpeg' => 'jpeg jpg jpe',
|
||||
'image/png' => 'png',
|
||||
'image/prs.btif' => 'btif',
|
||||
'image/svg+xml' => 'svg svgz',
|
||||
'image/tiff' => 'tiff tif',
|
||||
'image/vnd.adobe.photoshop' => 'psd',
|
||||
'image/vnd.djvu' => 'djvu djv',
|
||||
'image/vnd.dwg' => 'dwg',
|
||||
'image/vnd.dxf' => 'dxf',
|
||||
'image/vnd.fastbidsheet' => 'fbs',
|
||||
'image/vnd.fpx' => 'fpx',
|
||||
'image/vnd.fst' => 'fst',
|
||||
'image/vnd.fujixerox.edmics-mmr' => 'mmr',
|
||||
'image/vnd.fujixerox.edmics-rlc' => 'rlc',
|
||||
'image/vnd.ms-modi' => 'mdi',
|
||||
'image/vnd.net-fpx' => 'npx',
|
||||
'image/vnd.wap.wbmp' => 'wbmp',
|
||||
'image/vnd.xiff' => 'xif',
|
||||
'image/x-cmu-raster' => 'ras',
|
||||
'image/x-cmx' => 'cmx',
|
||||
'image/x-freehand' => 'fh fhc fh4 fh5 fh7',
|
||||
'image/x-icon' => 'ico',
|
||||
'image/x-pcx' => 'pcx',
|
||||
'image/x-pict' => 'pic pct',
|
||||
'image/x-portable-anymap' => 'pnm',
|
||||
'image/x-portable-bitmap' => 'pbm',
|
||||
'image/x-portable-graymap' => 'pgm',
|
||||
'image/x-portable-pixmap' => 'ppm',
|
||||
'image/x-rgb' => 'rgb',
|
||||
'image/x-xbitmap' => 'xbm',
|
||||
'image/x-xpixmap' => 'xpm',
|
||||
'image/x-xwindowdump' => 'xwd',
|
||||
'message/rfc822' => 'eml mime',
|
||||
'model/iges' => 'igs iges',
|
||||
'model/mesh' => 'msh mesh silo',
|
||||
'model/vnd.dwf' => 'dwf',
|
||||
'model/vnd.gdl' => 'gdl',
|
||||
'model/vnd.gtw' => 'gtw',
|
||||
'model/vnd.mts' => 'mts',
|
||||
'model/vnd.vtu' => 'vtu',
|
||||
'model/vrml' => 'wrl vrml',
|
||||
'text/calendar' => 'ics ifb',
|
||||
'text/css' => 'css',
|
||||
'text/csv' => 'csv',
|
||||
'text/html' => 'html htm',
|
||||
'text/plain' => 'txt text conf def list log in',
|
||||
'text/prs.lines.tag' => 'dsc',
|
||||
'text/richtext' => 'rtx',
|
||||
'text/sgml' => 'sgml sgm',
|
||||
'text/tab-separated-values' => 'tsv',
|
||||
'text/troff' => 't tr roff man me ms',
|
||||
'text/uri-list' => 'uri uris urls',
|
||||
'text/vnd.curl' => 'curl',
|
||||
'text/vnd.curl.dcurl' => 'dcurl',
|
||||
'text/vnd.curl.scurl' => 'scurl',
|
||||
'text/vnd.curl.mcurl' => 'mcurl',
|
||||
'text/vnd.fly' => 'fly',
|
||||
'text/vnd.fmi.flexstor' => 'flx',
|
||||
'text/vnd.graphviz' => 'gv',
|
||||
'text/vnd.in3d.3dml' => '3dml',
|
||||
'text/vnd.in3d.spot' => 'spot',
|
||||
'text/vnd.sun.j2me.app-descriptor' => 'jad',
|
||||
'text/vnd.wap.wml' => 'wml',
|
||||
'text/vnd.wap.wmlscript' => 'wmls',
|
||||
'text/x-asm' => 's asm',
|
||||
'text/x-c' => 'c cc cxx cpp h hh dic',
|
||||
'text/x-fortran' => 'f for f77 f90',
|
||||
'text/x-pascal' => 'p pas',
|
||||
'text/x-java-source' => 'java',
|
||||
'text/x-setext' => 'etx',
|
||||
'text/x-uuencode' => 'uu',
|
||||
'text/x-vcalendar' => 'vcs',
|
||||
'text/x-vcard' => 'vcf',
|
||||
'video/3gpp' => '3gp',
|
||||
'video/3gpp2' => '3g2',
|
||||
'video/h261' => 'h261',
|
||||
'video/h263' => 'h263',
|
||||
'video/h264' => 'h264',
|
||||
'video/jpeg' => 'jpgv',
|
||||
'video/jpm' => 'jpm jpgm',
|
||||
'video/mj2' => 'mj2 mjp2',
|
||||
'video/mp4' => 'mp4 mp4v mpg4',
|
||||
'video/mpeg' => 'mpeg mpg mpe m1v m2v',
|
||||
'video/ogg' => 'ogg ogv',
|
||||
'video/quicktime' => 'qt mov',
|
||||
'video/vnd.fvt' => 'fvt',
|
||||
'video/vnd.mpegurl' => 'mxu m4u',
|
||||
'video/vnd.ms-playready.media.pyv' => 'pyv',
|
||||
'video/vnd.vivo' => 'viv',
|
||||
'video/x-f4v' => 'f4v',
|
||||
'video/x-fli' => 'fli',
|
||||
'video/x-flv' => 'flv',
|
||||
'video/x-m4v' => 'm4v',
|
||||
'video/x-ms-asf' => 'asf asx wmv',
|
||||
'video/x-ms-wm' => 'wm',
|
||||
'video/x-ms-wmv' => 'wmv',
|
||||
'video/x-ms-wmx' => 'wmx',
|
||||
'video/x-ms-wvx' => 'wvx',
|
||||
'video/x-msvideo' => 'avi',
|
||||
'video/x-sgi-movie' => 'movie',
|
||||
'video/webm' => 'webm',
|
||||
'x-conference/x-cooltalk' => 'ice',
|
||||
);
|
||||
|
||||
/**
|
||||
* $mimes getter - see $mimes.
|
||||
*/
|
||||
private static function getMimes()
|
||||
{
|
||||
return self::$mimes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mime type from the $mimes array.
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function getMime($type)
|
||||
{
|
||||
// get mimetype array
|
||||
$mimes = self::getMimes();
|
||||
|
||||
if (array_key_exists($type, $mimes)) {
|
||||
return explode(' ', $mimes[$type]);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static function isSupported($extension)
|
||||
{
|
||||
// get mimetype array
|
||||
$mimes = self::getMimes();
|
||||
|
||||
$supported = false;
|
||||
|
||||
foreach(array_values($mimes) as $mime) {
|
||||
if (in_array($extension, explode(' ', $mime))) {
|
||||
$supported = true;
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
return $supported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check file mime type.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $path
|
||||
* @param string $type
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function check($name, $path)
|
||||
{
|
||||
$extension = strtolower(substr($name, strrpos($name, '.') + 1));
|
||||
$mimetype = null;
|
||||
|
||||
// if the extension is allowed, but no mimetype reference is found, let it through...
|
||||
if (self::isSupported($extension) === false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (function_exists('finfo_open')) {
|
||||
if (!$finfo = new finfo(FILEINFO_MIME_TYPE)) {
|
||||
return true;
|
||||
}
|
||||
$mimetype = $finfo->file($path);
|
||||
} elseif (function_exists('mime_content_type')) {
|
||||
$mimetype = @mime_content_type($path);
|
||||
}
|
||||
|
||||
if ($mimetype) {
|
||||
$mime = self::getMime($mimetype);
|
||||
|
||||
if ($mime) {
|
||||
if (!in_array($extension, $mime)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// server doesn't support mime type check, let it through...
|
||||
return true;
|
||||
}
|
||||
}
|
||||
1692
components/com_jce/editor/libraries/classes/mobile.php
Normal file
1692
components/com_jce/editor/libraries/classes/mobile.php
Normal file
File diff suppressed because one or more lines are too long
397
components/com_jce/editor/libraries/classes/packer.php
Normal file
397
components/com_jce/editor/libraries/classes/packer.php
Normal file
@@ -0,0 +1,397 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
class WFPacker extends JObject
|
||||
{
|
||||
const IMPORT_RX = '#@import.*?(?:\(([^\)]+)\);|(?:[\'"]([^\'"]+)[\'"]);)#i'; // match @import url('...'); or @import '...'; or @import "...";
|
||||
|
||||
protected $files = array();
|
||||
protected $type = 'javascript';
|
||||
protected $text = '';
|
||||
protected $start = '';
|
||||
protected $end = '';
|
||||
protected static $imports = array();
|
||||
|
||||
/**
|
||||
* Constructor activating the default information of the class.
|
||||
*/
|
||||
public function __construct($config = array())
|
||||
{
|
||||
$this->setProperties($config);
|
||||
}
|
||||
|
||||
public function setFiles($files = array())
|
||||
{
|
||||
$this->files = $files;
|
||||
}
|
||||
|
||||
public function getFiles()
|
||||
{
|
||||
return $this->files;
|
||||
}
|
||||
|
||||
public function setText($text = '')
|
||||
{
|
||||
$this->text = $text;
|
||||
}
|
||||
|
||||
public function setContentStart($start = '')
|
||||
{
|
||||
$this->start = $start;
|
||||
}
|
||||
|
||||
public function getContentStart()
|
||||
{
|
||||
return $this->start;
|
||||
}
|
||||
|
||||
public function setContentEnd($end = '')
|
||||
{
|
||||
$this->end = $end;
|
||||
}
|
||||
|
||||
public function getContentEnd()
|
||||
{
|
||||
return $this->end;
|
||||
}
|
||||
|
||||
public function setType($type)
|
||||
{
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get encoding.
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved
|
||||
*/
|
||||
private static function getEncoding()
|
||||
{
|
||||
if (!isset($_SERVER['HTTP_ACCEPT_ENCODING'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$encoding = false;
|
||||
|
||||
if (false !== strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) {
|
||||
$encoding = 'gzip';
|
||||
}
|
||||
|
||||
if (false !== strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'x-gzip')) {
|
||||
$encoding = 'x-gzip';
|
||||
}
|
||||
|
||||
return $encoding;
|
||||
}
|
||||
|
||||
private function getEtag($hash)
|
||||
{
|
||||
if (strpos($hash, '"') !== 0) {
|
||||
$hash = '"' . $hash . '"';
|
||||
}
|
||||
|
||||
return $hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pack and output content based on type.
|
||||
*
|
||||
* @param bool|true $minify
|
||||
* @param bool|true $cache
|
||||
* @param bool|false $gzip
|
||||
* Contains some code from libraries/joomla/cache/controller/page.php - Copyright (C) 2005 - 2015 Open Source Matters, Inc. All rights reserved
|
||||
*/
|
||||
public function pack($minify = true, $cache_validation = true, $gzip = false)
|
||||
{
|
||||
$type = $this->getType();
|
||||
|
||||
ob_start();
|
||||
|
||||
// Headers
|
||||
if ($type == 'javascript') {
|
||||
header('Content-type: application/javascript; charset: UTF-8');
|
||||
}
|
||||
|
||||
if ($type == 'css') {
|
||||
header('Content-type: text/css; charset: UTF-8');
|
||||
}
|
||||
|
||||
// encoding
|
||||
header('Vary: Accept-Encoding');
|
||||
|
||||
// cache control
|
||||
header('Cache-Control: max-age=0,no-cache');
|
||||
|
||||
$files = $this->getFiles();
|
||||
|
||||
$content = $this->getContentStart();
|
||||
|
||||
if (empty($files)) {
|
||||
$content .= $this->getText();
|
||||
} else {
|
||||
foreach ($files as $file) {
|
||||
$content .= $this->getText($file, $minify);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->getType() == 'css') {
|
||||
// move external import rules to top
|
||||
foreach (array_unique(self::$imports) as $import) {
|
||||
if (strpos($import, '//') !== false) {
|
||||
$content = '@import url("' . $import . '");' . $content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$content .= $this->getContentEnd();
|
||||
|
||||
// trim content
|
||||
$content = trim($content);
|
||||
|
||||
// force browser caching using an E-tag
|
||||
if ($cache_validation) {
|
||||
// get content hash
|
||||
$hash = md5(implode(' ', array_map('basename', $files)) . $content);
|
||||
// create E-tag
|
||||
$etag = $this->getEtag($hash);
|
||||
// set etag header
|
||||
header('ETag: ' . $etag);
|
||||
|
||||
// check for sent etag against hash
|
||||
if (!headers_sent() && isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
|
||||
$_etag = stripslashes($_SERVER['HTTP_IF_NONE_MATCH']);
|
||||
|
||||
if ($_etag && $_etag === $etag) {
|
||||
header('HTTP/1.x 304 Not Modified', true);
|
||||
exit(ob_get_clean());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate GZIP'd content
|
||||
if ($gzip) {
|
||||
$encoding = self::getEncoding();
|
||||
|
||||
$zlib = function_exists('ini_get') && extension_loaded('zlib') && ini_get('zlib.output_compression');
|
||||
|
||||
if (!empty($encoding) && !$zlib && function_exists('gzencode')) {
|
||||
header('Content-Encoding: ' . $encoding);
|
||||
$content = gzencode($content, 4, FORCE_GZIP);
|
||||
}
|
||||
}
|
||||
|
||||
// stream to client
|
||||
echo $content;
|
||||
|
||||
exit(ob_get_clean());
|
||||
}
|
||||
|
||||
protected function jsmin($data)
|
||||
{
|
||||
// remove header comments
|
||||
return preg_replace('#^\/\*[\s\S]+?\*\/#', '', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple CSS Minifier
|
||||
* https://github.com/GaryJones/Simple-PHP-CSS-Minification.
|
||||
*
|
||||
* @param $data Data string to minify
|
||||
*/
|
||||
protected function cssmin($css)
|
||||
{
|
||||
// Normalize whitespace
|
||||
//$css = preg_replace('/\s+/', ' ', $css);
|
||||
// Remove comment blocks, everything between /* and */, unless
|
||||
// preserved with /*! ... */
|
||||
//$css = preg_replace('/\/\*[^\!](.*?)\*\//', '', $css);
|
||||
// Remove space after , : ; { }
|
||||
//$css = preg_replace('/(,|:|;|\{|}) /', '$1', $css);
|
||||
// Remove space before , ; { }
|
||||
//$css = preg_replace('/ (,|;|\{|})/', '$1', $css);
|
||||
// Strips leading 0 on decimal values (converts 0.5px into .5px)
|
||||
//$css = preg_replace('/(:| )0\.([0-9]+)(%|em|ex|px|in|cm|mm|pt|pc)/i', '${1}.${2}${3}', $css);
|
||||
// Strips units if value is 0 (converts 0px to 0)
|
||||
//$css = preg_replace('/(:| )(\.?)0(%|em|ex|px|in|cm|mm|pt|pc)/i', '${1}0', $css);
|
||||
// Converts all zeros value into short-hand
|
||||
//$css = preg_replace('/0 0 0 0/', '0', $css);
|
||||
// Shortern 6-character hex color codes to 3-character where possible
|
||||
//$css = preg_replace('/#([a-f0-9])\\1([a-f0-9])\\2([a-f0-9])\\3/i', '#\1\2\3', $css);
|
||||
|
||||
require_once __DIR__ . '/vendor/cssmin/cssmin.php';
|
||||
|
||||
try {
|
||||
$css = CssMin::minify($css);
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
|
||||
return trim($css);
|
||||
}
|
||||
|
||||
/**
|
||||
* Import CSS from a file.
|
||||
*
|
||||
* @param file File path where data comes from
|
||||
* @param $data Data from file
|
||||
*/
|
||||
protected function importCss($data, $file)
|
||||
{
|
||||
if (preg_match_all(self::IMPORT_RX, $data, $matches)) {
|
||||
$data = '';
|
||||
|
||||
foreach ($matches[1] as $match) {
|
||||
// clean up url
|
||||
$match = str_replace(array('url', '"', "'", '(', ')'), '', $match);
|
||||
// trim
|
||||
$match = trim($match);
|
||||
|
||||
if ($match) {
|
||||
// external url, skip it
|
||||
if (strpos($match, '//') !== false) {
|
||||
// add to imports list
|
||||
self::$imports[] = $match;
|
||||
continue;
|
||||
}
|
||||
|
||||
// url has a query, remove
|
||||
if (strpos($match, '?') !== false) {
|
||||
$match = substr($match, 0, strpos($match, '?'));
|
||||
}
|
||||
|
||||
if (strpos($match, '&') !== false) {
|
||||
$match = substr($match, 0, strpos($match, '&'));
|
||||
}
|
||||
|
||||
// get full path
|
||||
$path = realpath($this->get('_cssbase') . '/' . $match);
|
||||
|
||||
// already import, don't repeat!
|
||||
if (in_array($path, self::$imports)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// get data
|
||||
$data .= $this->getText($path);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
protected function compileLess($string, $path)
|
||||
{
|
||||
$less = new lessc();
|
||||
// add file directory
|
||||
$less->addImportDir($path);
|
||||
// add joomla media folder
|
||||
$less->addImportDir(JPATH_SITE . '/media');
|
||||
|
||||
try {
|
||||
return $less->compile($string);
|
||||
} catch (Exception $e) {
|
||||
return '/* LESS file could not be compiled due to error - ' . $e->getMessage() . ' */';
|
||||
}
|
||||
}
|
||||
|
||||
protected function getText($file = null, $minify = true)
|
||||
{
|
||||
if ($file && is_file($file)) {
|
||||
$text = file_get_contents($file);
|
||||
|
||||
if ($text) {
|
||||
// process css files
|
||||
if ($this->getType() == 'css') {
|
||||
// compile less files
|
||||
if (preg_match('#\.less$#', $file)) {
|
||||
$text = $this->compileLess($text, dirname($file));
|
||||
}
|
||||
|
||||
if ($minify) {
|
||||
// minify
|
||||
$text = $this->cssmin($text, $file);
|
||||
}
|
||||
|
||||
// add to imports list
|
||||
self::$imports[] = $file;
|
||||
|
||||
if (strpos($text, '@import') !== false) {
|
||||
// store the base path of the current file
|
||||
$this->set('_cssbase', dirname($file));
|
||||
|
||||
// process import rules
|
||||
$text = $this->importCss($text, $file) . preg_replace(self::IMPORT_RX, '', $text);
|
||||
}
|
||||
|
||||
// store the base path of the current file
|
||||
$this->set('_imgbase', dirname($file));
|
||||
|
||||
// process urls
|
||||
$text = preg_replace_callback('#url\s?\([\'"]?([^\'"\))]+)[\'"]?\)#', array('WFPacker', 'processPaths'), $text);
|
||||
}
|
||||
// make sure text ends in a semi-colon;
|
||||
if ($this->getType() == 'javascript') {
|
||||
$text = rtrim(trim($text), ';') . ';';
|
||||
|
||||
if ($minify) {
|
||||
$text = $this->jsmin($text);
|
||||
}
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
protected function processPaths($data)
|
||||
{
|
||||
if (isset($data[1])) {
|
||||
if (strpos($data[1], '//') === false) {
|
||||
$path = parse_url($data[1], PHP_URL_PATH);
|
||||
|
||||
if (empty($path)) {
|
||||
$path = $data[1];
|
||||
}
|
||||
|
||||
// get query, if any, eg: ?v=273
|
||||
$query = parse_url($data[1], PHP_URL_QUERY);
|
||||
|
||||
if (empty($query)) {
|
||||
$query = "";
|
||||
} else {
|
||||
$query = "?" . $query;
|
||||
}
|
||||
|
||||
$path = str_replace(JPATH_SITE, '', realpath($this->get('_imgbase') . '/' . $path));
|
||||
|
||||
if ($path) {
|
||||
return "url('" . JURI::root(true) . str_replace('\\', '/', $path) . $query . "')";
|
||||
}
|
||||
|
||||
return "url('" . $data[1] . "')";
|
||||
}
|
||||
|
||||
return $data[1];
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
628
components/com_jce/editor/libraries/classes/plugin.php
Normal file
628
components/com_jce/editor/libraries/classes/plugin.php
Normal file
@@ -0,0 +1,628 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* JCE class.
|
||||
*/
|
||||
class WFEditorPlugin extends JObject
|
||||
{
|
||||
// Editor Plugin instance
|
||||
private static $instance;
|
||||
|
||||
// array of alerts
|
||||
private $_alerts = array();
|
||||
|
||||
// plugin name
|
||||
protected $name = '';
|
||||
|
||||
/**
|
||||
* Constructor activating the default information of the class.
|
||||
*/
|
||||
public function __construct($config = array())
|
||||
{
|
||||
// Call parent
|
||||
parent::__construct();
|
||||
|
||||
// get plugin name from url, fallback to default name if set
|
||||
$name = JFactory::getApplication()->input->getCmd('plugin', $this->get('name'));
|
||||
|
||||
// get name and caller from plugin name
|
||||
if (strpos($name, '.') !== false) {
|
||||
list($name, $caller) = explode('.', $name);
|
||||
|
||||
// validate then store caller
|
||||
if ($caller !== $name) {
|
||||
|
||||
$profile = $this->getProfile();
|
||||
|
||||
if (!empty($profile)) {
|
||||
if (in_array($caller, explode(',', $profile->plugins))) {
|
||||
$this->set('caller', $caller);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// re-set the "name" value
|
||||
$this->set('name', $name);
|
||||
|
||||
if (!array_key_exists('base_path', $config)) {
|
||||
$config['base_path'] = WF_EDITOR_PLUGINS . '/' . $name;
|
||||
}
|
||||
|
||||
if (!defined('WF_EDITOR_PLUGIN')) {
|
||||
define('WF_EDITOR_PLUGIN', $config['base_path']);
|
||||
}
|
||||
|
||||
if (!array_key_exists('view_path', $config)) {
|
||||
$config['view_path'] = $config['base_path'];
|
||||
}
|
||||
|
||||
if (!array_key_exists('layout', $config)) {
|
||||
$config['layout'] = 'default';
|
||||
}
|
||||
|
||||
if (!array_key_exists('template_path', $config)) {
|
||||
$config['template_path'] = $config['base_path'] . '/tmpl';
|
||||
}
|
||||
|
||||
$this->setProperties($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to a editor object.
|
||||
*
|
||||
* This method must be invoked as:
|
||||
* <pre> $browser =JCE::getInstance();</pre>
|
||||
*
|
||||
* @return JCE The editor object
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public static function getInstance($config = array())
|
||||
{
|
||||
if (!isset(self::$instance)) {
|
||||
self::$instance = new self($config);
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plugin View.
|
||||
*
|
||||
* @return WFView
|
||||
*/
|
||||
public function getView()
|
||||
{
|
||||
static $view;
|
||||
|
||||
if (!is_object($view)) {
|
||||
// create plugin view
|
||||
$view = new WFView(array(
|
||||
'view_path' => $this->get('base_path'),
|
||||
'template_path' => $this->get('template_path'),
|
||||
'name' => $this->get('name'),
|
||||
'layout' => $this->get('layout'),
|
||||
));
|
||||
}
|
||||
|
||||
$view->plugin = $this;
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
protected function getVersion()
|
||||
{
|
||||
$wf = WFApplication::getInstance();
|
||||
|
||||
return $wf->getVersion();
|
||||
}
|
||||
|
||||
protected function getProfile($plugin = '')
|
||||
{
|
||||
$wf = WFApplication::getInstance();
|
||||
|
||||
return $wf->getProfile($plugin);
|
||||
}
|
||||
|
||||
protected function getPluginVersion()
|
||||
{
|
||||
$manifest = $this->get('base_path') . '/' . $this->get('name') . '.xml';
|
||||
|
||||
$version = '';
|
||||
|
||||
if (is_file($manifest)) {
|
||||
$version = md5_file($manifest);
|
||||
}
|
||||
|
||||
return $version;
|
||||
}
|
||||
|
||||
protected function isRtl()
|
||||
{
|
||||
$language = JFactory::getLanguage();
|
||||
|
||||
if ($language->getTag() === WFLanguage::getTag()) {
|
||||
return $language->isRTL();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function initialize()
|
||||
{
|
||||
$app = JFactory::getApplication();
|
||||
$wf = WFApplication::getInstance();
|
||||
|
||||
$version = $this->getVersion();
|
||||
$name = $this->getName();
|
||||
|
||||
// set default plugin version
|
||||
$plugin_version = $this->getPluginVersion();
|
||||
|
||||
// add plugin version
|
||||
if ($plugin_version && $plugin_version != $version) {
|
||||
$version .= $plugin_version;
|
||||
}
|
||||
|
||||
// create the document
|
||||
$document = WFDocument::getInstance(array(
|
||||
'version' => $version,
|
||||
'title' => JText::_('WF_' . strtoupper($this->getName() . '_TITLE')),
|
||||
'name' => $name,
|
||||
'language' => WFLanguage::getTag(),
|
||||
'direction' => $this->isRtl() ? 'rtl' : 'ltr',
|
||||
'compress_javascript' => $this->getParam('editor.compress_javascript', 0),
|
||||
'compress_css' => $this->getParam('editor.compress_css', 0),
|
||||
));
|
||||
|
||||
// set standalone mode
|
||||
$document->set('standalone', $wf->input->getInt('standalone', 0));
|
||||
|
||||
JFactory::getApplication()->triggerEvent('onWfPluginInit', array($this));
|
||||
}
|
||||
|
||||
public function execute()
|
||||
{
|
||||
$this->initialize();
|
||||
|
||||
// process requests if any - method will end here
|
||||
WFRequest::getInstance()->process();
|
||||
|
||||
$this->display();
|
||||
|
||||
$document = WFDocument::getInstance();
|
||||
|
||||
// ini language
|
||||
$document->addScript(array(JURI::base(true) . '/index.php?option=com_jce&' . $document->getQueryString(
|
||||
array('task' => 'plugin.loadlanguages', 'lang' => WFLanguage::getCode())
|
||||
)), 'joomla');
|
||||
|
||||
// pack assets if required
|
||||
$document->pack(true, $this->getParam('editor.compress_gzip', 0));
|
||||
|
||||
// get the view
|
||||
$view = $this->getView();
|
||||
|
||||
// set body output
|
||||
$document->setBody($view->loadTemplate());
|
||||
|
||||
$document->render();
|
||||
}
|
||||
|
||||
public function loadlanguages()
|
||||
{
|
||||
$name = $this->get('name');
|
||||
|
||||
$parser = new WFLanguageParser(array(
|
||||
'plugins' => array('core' => array($name), 'external' => array()),
|
||||
'sections' => array('dlg', $name . '_dlg', 'colorpicker'),
|
||||
'mode' => 'plugin',
|
||||
'language' => WFLanguage::getTag(),
|
||||
));
|
||||
|
||||
$data = $parser->load();
|
||||
$parser->output($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display plugin.
|
||||
*/
|
||||
public function display()
|
||||
{
|
||||
// check session on get request
|
||||
JSession::checkToken('get') or jexit(JText::_('JINVALID_TOKEN'));
|
||||
|
||||
$this->initialize();
|
||||
|
||||
jimport('joomla.filesystem.folder');
|
||||
$document = WFDocument::getInstance();
|
||||
|
||||
if ($document->get('standalone') == 0) {
|
||||
$document->addScript(array('tiny_mce_popup'), 'tiny_mce');
|
||||
}
|
||||
|
||||
$document->addScript(array('jquery.min'), 'jquery');
|
||||
$document->addScript(array('jquery-ui.min'), 'jquery');
|
||||
$document->addScript(array('jquery-ui.touch.min'), 'jquery');
|
||||
|
||||
$document->addScript(array('plugin.min.js'));
|
||||
$document->addStyleSheet(array('plugin.min.css'), 'libraries');
|
||||
|
||||
// add custom plugin.css if exists
|
||||
if (is_file(JPATH_SITE . '/media/jce/css/plugin.css')) {
|
||||
$document->addStyleSheet(array('media/jce/css/plugin.css'), 'joomla');
|
||||
}
|
||||
|
||||
JFactory::getApplication()->triggerEvent('onWfPluginDisplay', array($this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the plugin name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->get('name');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the plugin name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCaller()
|
||||
{
|
||||
return $this->get('caller');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default values for a plugin.
|
||||
* Key / Value pairs will be retrieved from the profile or plugin manifest.
|
||||
*
|
||||
* @param array $defaults
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDefaults($fieldset = 'defaults', $options = array())
|
||||
{
|
||||
$name = $this->getName();
|
||||
$caller = $this->get('caller');
|
||||
|
||||
if ($caller) {
|
||||
$name = $caller;
|
||||
}
|
||||
|
||||
$defaults = array();
|
||||
$exclude = array();
|
||||
|
||||
if (isset($options['defaults'])) {
|
||||
$defaults = $options['defaults'];
|
||||
}
|
||||
|
||||
if (isset($options['exclude'])) {
|
||||
$exclude = $options['exclude'];
|
||||
}
|
||||
|
||||
// get manifest path
|
||||
$manifest = $this->get('base_path') . '/' . $name . '.xml';
|
||||
|
||||
// use the plugin name as the form
|
||||
$form_id = $name;
|
||||
|
||||
// parameter group
|
||||
if (isset($options['group'])) {
|
||||
$name .= '.' . $options['group'];
|
||||
}
|
||||
|
||||
if (isset($options['manifest'])) {
|
||||
$manifest = $options['manifest'];
|
||||
// create extension specific form id
|
||||
$form_id .= '.' . basename($manifest, '.xml');
|
||||
}
|
||||
|
||||
// get parameter defaults
|
||||
if (is_file($manifest)) {
|
||||
$form = JForm::getInstance('com_jce.plugin.' . $form_id, $manifest, array('load_data' => false), true, '//extension');
|
||||
$fields = $form->getFieldset($fieldset);
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$key = $field->getAttribute('name');
|
||||
|
||||
if (!$key || $key === "buttons") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_array($key, $exclude)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$def = (string) $field->getAttribute('default');
|
||||
|
||||
// get parameter default value if set, use the specific plugin
|
||||
$value = $this->getParam($name . '.' . $key, $def);
|
||||
|
||||
// only use non-empty values
|
||||
if ($value !== '') {
|
||||
$defaults[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $defaults;
|
||||
}
|
||||
|
||||
public function getDefaultAttributes()
|
||||
{
|
||||
$defaults = $this->getDefaults();
|
||||
|
||||
$attribs = array();
|
||||
$styles = array();
|
||||
|
||||
foreach ($defaults as $key => $value) {
|
||||
switch ($key) {
|
||||
case 'align':
|
||||
// convert to float
|
||||
if ($value == 'left' || $value == 'right') {
|
||||
$key = 'float';
|
||||
} else {
|
||||
$key = 'vertical-align';
|
||||
}
|
||||
|
||||
// check for value and exclude border state parameter
|
||||
if ($value != '') {
|
||||
$styles[str_replace('_', '-', $key)] = $value;
|
||||
}
|
||||
break;
|
||||
case 'border_width':
|
||||
case 'border_style':
|
||||
case 'border_color':
|
||||
// only if border state set
|
||||
$value = $defaults['border'] ? $value : '';
|
||||
|
||||
// add px unit to border-width
|
||||
if ($value && $key == 'border_width' && is_numeric($value)) {
|
||||
$value .= 'px';
|
||||
}
|
||||
|
||||
// check for value and exclude border state parameter
|
||||
if ($value != '') {
|
||||
$styles[str_replace('_', '-', $key)] = $value;
|
||||
}
|
||||
|
||||
break;
|
||||
case 'margin_left':
|
||||
case 'margin_right':
|
||||
case 'margin_top':
|
||||
case 'margin_bottom':
|
||||
// add px unit to border-width
|
||||
if ($value && is_numeric($value)) {
|
||||
$value .= 'px';
|
||||
}
|
||||
|
||||
// check for value and exclude border state parameter
|
||||
if ($value != '') {
|
||||
$styles[str_replace('_', '-', $key)] = $value;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
if ($key == 'direction') {
|
||||
$key = 'dir';
|
||||
}
|
||||
|
||||
if ($key == 'classes') {
|
||||
$key = 'class';
|
||||
}
|
||||
|
||||
if ($value !== '') {
|
||||
$attribs[$key] = $value;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// styles object
|
||||
if (!empty($styles)) {
|
||||
$attribs['styles'] = $styles;
|
||||
}
|
||||
|
||||
return $attribs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the user is in an authorized group
|
||||
* Check the users group is authorized to use the plugin.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function checkPlugin($plugin = null)
|
||||
{
|
||||
if ($plugin) {
|
||||
// check existence of plugin directory
|
||||
if (is_dir(WF_EDITOR_PLUGINS . '/' . $plugin)) {
|
||||
// get profile
|
||||
$profile = $this->getProfile($plugin);
|
||||
// check for valid object and profile id
|
||||
return is_object($profile) && isset($profile->id);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an alert array to the stack.
|
||||
*
|
||||
* @param object $class Alert classname
|
||||
* @param object $title Alert title
|
||||
* @param object $text Alert text
|
||||
*/
|
||||
protected function addAlert($class = 'info', $title = '', $text = '')
|
||||
{
|
||||
$alerts = $this->getAlerts();
|
||||
|
||||
$alerts[] = array(
|
||||
'class' => $class,
|
||||
'title' => $title,
|
||||
'text' => $text,
|
||||
);
|
||||
|
||||
$this->set('_alerts', $alerts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current alerts.
|
||||
*
|
||||
* @return array Alerts
|
||||
*/
|
||||
private function getAlerts()
|
||||
{
|
||||
return $this->get('_alerts');
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a url to path.
|
||||
*
|
||||
* @param string The url to convert
|
||||
*
|
||||
* @return string Full path to file
|
||||
*/
|
||||
public function urlToPath($url)
|
||||
{
|
||||
$document = WFDocument::getInstance();
|
||||
|
||||
return $document->urlToPath($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an image url.
|
||||
*
|
||||
* @param string The file to load including path and extension eg: libaries.image.gif
|
||||
*
|
||||
* @return string Image url
|
||||
*/
|
||||
public function image($image, $root = 'libraries')
|
||||
{
|
||||
$document = WFDocument::getInstance();
|
||||
|
||||
return $document->image($image, $root);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load & Call an extension.
|
||||
*
|
||||
* @param array $config
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function loadExtensions($type, $extension = null, $config = array())
|
||||
{
|
||||
return WFExtension::loadExtensions($type, $extension, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile plugin settings from defaults and alerts.
|
||||
*
|
||||
* @param array $settings
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSettings($settings = array())
|
||||
{
|
||||
$default = array(
|
||||
'alerts' => $this->getAlerts(),
|
||||
'defaults' => $this->getDefaults(),
|
||||
);
|
||||
|
||||
$settings = array_merge($default, $settings);
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
public function getParams($options = array())
|
||||
{
|
||||
$wf = WFApplication::getInstance();
|
||||
|
||||
return $wf->getParams($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a parameter by key.
|
||||
*
|
||||
* @param string $key Parameter key eg: editor.width
|
||||
* @param mixed $fallback Fallback value
|
||||
* @param mixed $default Default value
|
||||
* @param string $type Variable type eg: string, boolean, integer, array
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getParam($key, $fallback = '', $default = '', $type = 'string')
|
||||
{
|
||||
// get plugin name
|
||||
$name = $this->getName();
|
||||
// get caller if any
|
||||
$caller = $this->get('caller');
|
||||
|
||||
// get all keys
|
||||
$keys = explode('.', $key);
|
||||
$wf = WFApplication::getInstance();
|
||||
|
||||
// root key set
|
||||
if ($keys[0] == 'editor' || $keys[0] == $name || $keys[0] == $caller) {
|
||||
return $wf->getParam($key, $fallback, $default, $type);
|
||||
// no root key set, treat as shared param
|
||||
} else {
|
||||
// get fallback param from editor key
|
||||
$fallback = $wf->getParam('editor.' . $key, $fallback, $default, $type);
|
||||
|
||||
if ($caller) {
|
||||
// get fallback from plugin (with editor parameter as fallback)
|
||||
$fallback = $wf->getParam($name . '.' . $key, $fallback, $default, $type);
|
||||
$name = $caller;
|
||||
}
|
||||
|
||||
// reset the $default to prevent clearing
|
||||
if ($fallback === $default) {
|
||||
$default = '';
|
||||
}
|
||||
|
||||
// return parameter
|
||||
return $wf->getParam($name . '.' . $key, $fallback, $default, $type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Named wrapper to check access to a feature.
|
||||
*
|
||||
* @param string The feature to check, eg: upload
|
||||
* @param mixed The defalt value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function checkAccess($option, $default = 0)
|
||||
{
|
||||
return (bool) $this->getParam($option, $default);
|
||||
}
|
||||
|
||||
protected function allowEvents()
|
||||
{
|
||||
if ((bool) $this->getParam('editor.allow_javascript')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (bool) $this->getParam('editor.allow_event_attributes');
|
||||
}
|
||||
}
|
||||
234
components/com_jce/editor/libraries/classes/request.php
Normal file
234
components/com_jce/editor/libraries/classes/request.php
Normal file
@@ -0,0 +1,234 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
final class WFRequest extends JObject
|
||||
{
|
||||
protected static $instance;
|
||||
|
||||
protected $requests = array();
|
||||
|
||||
/**
|
||||
* Constructor activating the default information of the class.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to a WFRequest object.
|
||||
*
|
||||
* This method must be invoked as:
|
||||
* <pre> $request = WFRequest::getInstance();</pre>
|
||||
*
|
||||
* @return object WFRequest
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
if (!isset(self::$instance)) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Request function.
|
||||
*
|
||||
* @param array $function An array containing the function and object
|
||||
*/
|
||||
public function register($function)
|
||||
{
|
||||
$object = new stdClass();
|
||||
|
||||
if (is_array($function)) {
|
||||
$ref = array_shift($function);
|
||||
$name = array_shift($function);
|
||||
|
||||
$object->fn = $name;
|
||||
$object->ref = $ref;
|
||||
|
||||
$this->requests[$name] = $object;
|
||||
} else {
|
||||
$object->fn = $function;
|
||||
$this->requests[$function] = $object;
|
||||
}
|
||||
}
|
||||
|
||||
private function isRegistered($function)
|
||||
{
|
||||
return array_key_exists($function, $this->requests);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a request function.
|
||||
*
|
||||
* @param string $function
|
||||
*/
|
||||
public function getFunction($function)
|
||||
{
|
||||
return $this->requests[$function];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the HTTP Request is a WFRequest.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isRequest()
|
||||
{
|
||||
return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') || (isset($_SERVER['CONTENT_TYPE']) && strpos($_SERVER['CONTENT_TYPE'], 'multipart') !== false);
|
||||
}
|
||||
|
||||
public function setRequest($request)
|
||||
{
|
||||
return $this->register($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check a request query for bad stuff.
|
||||
*
|
||||
* @param array $query
|
||||
*/
|
||||
private function checkQuery($query)
|
||||
{
|
||||
if (is_string($query)) {
|
||||
$query = array($query);
|
||||
}
|
||||
|
||||
// check for null byte
|
||||
foreach ($query as $key => $value) {
|
||||
if (is_array($value) || is_object($value)) {
|
||||
return self::checkQuery($value);
|
||||
}
|
||||
|
||||
if (is_array($key)) {
|
||||
return self::checkQuery($key);
|
||||
}
|
||||
|
||||
if (strpos($key, '\u0000') !== false || strpos($value, '\u0000') !== false) {
|
||||
JError::raiseError(403, 'RESTRICTED');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an ajax call and return result.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function process($array = false)
|
||||
{
|
||||
if ($this->isRequest() === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for request forgeries
|
||||
JSession::checkToken('request') or jexit(JText::_('JINVALID_TOKEN'));
|
||||
|
||||
$app = JFactory::getApplication();
|
||||
|
||||
// empty arguments
|
||||
$args = array();
|
||||
|
||||
$json = $app->input->getVar('json', '', 'POST', 'STRING', 2);
|
||||
$method = $app->input->getWord('method');
|
||||
|
||||
// get and encode json data
|
||||
if ($json) {
|
||||
// remove slashes
|
||||
$json = stripslashes($json);
|
||||
|
||||
// convert to JSON object
|
||||
$json = json_decode($json);
|
||||
}
|
||||
|
||||
// get current request id
|
||||
$id = empty($json->id) ? $app->input->getWord('id') : $json->id;
|
||||
|
||||
// create response
|
||||
$response = new WFResponse($id);
|
||||
|
||||
if ($method || $json) {
|
||||
// set request flag
|
||||
define('JCE_REQUEST', 1);
|
||||
|
||||
// check if valid json object
|
||||
if (is_object($json)) {
|
||||
// no function call
|
||||
if (isset($json->method) === false) {
|
||||
$response->setError(array('code' => -32600, 'message' => 'Invalid Request'))->send();
|
||||
}
|
||||
|
||||
// get function call
|
||||
$fn = $json->method;
|
||||
|
||||
// clean function
|
||||
$fn = JFilterInput::getInstance()->clean($fn, 'cmd');
|
||||
|
||||
// pass params to input and flatten
|
||||
if (!empty($json->params)) {
|
||||
// check query
|
||||
$this->checkQuery($json->params);
|
||||
|
||||
// merge array with args
|
||||
if (is_array($json->params)) {
|
||||
$args = array_merge($args, $json->params);
|
||||
// pass through string or object
|
||||
} else {
|
||||
$args[] = $json->params;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$fn = $method;
|
||||
$response->setHeaders(array('Content-type' => 'text/html;charset=UTF-8'));
|
||||
}
|
||||
|
||||
if (empty($fn) || $this->isRegistered($fn) === false) {
|
||||
$response->setError(array('code' => -32601, 'message' => 'Method not found'))->send();
|
||||
}
|
||||
|
||||
// get method
|
||||
$request = $this->getFunction($fn);
|
||||
|
||||
// create callable function
|
||||
$callback = array($request->ref, $request->fn);
|
||||
|
||||
// check function is callable
|
||||
if (is_callable($callback) === false) {
|
||||
$response->setError(array('code' => -32601, 'message' => 'Method not found'))->send();
|
||||
}
|
||||
|
||||
// create empty result
|
||||
$result = '';
|
||||
|
||||
try {
|
||||
$result = call_user_func_array($callback, (array) $args);
|
||||
|
||||
if (is_array($result) && !empty($result['error'])) {
|
||||
if (is_array($result['error'])) {
|
||||
$result['error'] = implode("\n", $result['error']);
|
||||
}
|
||||
|
||||
$response->setError(array('message' => $result['error']))->send();
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$response->setError(array('code' => $e->getCode(), 'message' => $e->getMessage()))->send();
|
||||
}
|
||||
|
||||
$response->setContent($result)->send();
|
||||
}
|
||||
|
||||
// default response
|
||||
$response->setError(array('code' => -32601, 'message' => 'The server returned an invalid response'))->send();
|
||||
}
|
||||
}
|
||||
122
components/com_jce/editor/libraries/classes/response.php
Normal file
122
components/com_jce/editor/libraries/classes/response.php
Normal file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
final class WFResponse
|
||||
{
|
||||
private $content = null;
|
||||
|
||||
private $id = null;
|
||||
|
||||
private $error = null;
|
||||
|
||||
private $headers = array(
|
||||
'Content-Type' => 'text/json;charset=UTF-8',
|
||||
);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param $id Request id
|
||||
* @param null $content Response content
|
||||
* @param array $headers Optional headers
|
||||
*/
|
||||
public function __construct($id, $content = null, $headers = array())
|
||||
{
|
||||
// et response content
|
||||
$this->setContent($content);
|
||||
|
||||
// set id
|
||||
$this->id = $id;
|
||||
|
||||
// set header
|
||||
$this->setHeaders($headers);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send response.
|
||||
*
|
||||
* @param array $data
|
||||
*/
|
||||
public function send($data = array())
|
||||
{
|
||||
$data = array_merge($data, array(
|
||||
'jsonrpc' => '2.0',
|
||||
'id' => $this->id,
|
||||
'result' => $this->getContent(),
|
||||
'error' => $this->getError(),
|
||||
));
|
||||
|
||||
ob_start();
|
||||
|
||||
// set custom headers
|
||||
foreach ($this->headers as $key => $value) {
|
||||
header($key.': '.$value);
|
||||
}
|
||||
|
||||
// set output headers
|
||||
header('Expires: Mon, 4 April 1984 05:00:00 GMT');
|
||||
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||
header('Cache-Control: post-check=0, pre-check=0', false);
|
||||
header('Pragma: no-cache');
|
||||
|
||||
// only echo response if an id is set
|
||||
if (!empty($this->id)) {
|
||||
echo json_encode($data);
|
||||
}
|
||||
|
||||
exit(ob_get_clean());
|
||||
}
|
||||
|
||||
public function getHeader()
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
|
||||
public function setHeaders($headers)
|
||||
{
|
||||
foreach ($headers as $key => $value) {
|
||||
$this->headers[$key] = $value;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $error
|
||||
*/
|
||||
public function setError($error = array('code' => -32603, 'message' => 'Internal error'))
|
||||
{
|
||||
$this->error = $error;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getError()
|
||||
{
|
||||
return $this->error;
|
||||
}
|
||||
|
||||
public function getContent()
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
|
||||
public function setContent($content)
|
||||
{
|
||||
$this->content = $content;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
222
components/com_jce/editor/libraries/classes/tabs.php
Normal file
222
components/com_jce/editor/libraries/classes/tabs.php
Normal file
@@ -0,0 +1,222 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
final class WFTabs extends JObject
|
||||
{
|
||||
private $_tabs = array();
|
||||
private $_panels = array();
|
||||
private $_paths = array();
|
||||
|
||||
/**
|
||||
* Constructor activating the default information of the class.
|
||||
*/
|
||||
public function __construct($config = array())
|
||||
{
|
||||
if (!array_key_exists('base_path', $config)) {
|
||||
$config['base_path'] = WF_EDITOR_LIBRARIES;
|
||||
}
|
||||
|
||||
$this->setProperties($config);
|
||||
|
||||
if (array_key_exists('template_path', $config)) {
|
||||
$this->addTemplatePath($config['template_path']);
|
||||
} else {
|
||||
$this->addTemplatePath($this->get('base_path') . '/tmpl');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a reference to a WFTabs object.
|
||||
*
|
||||
* This method must be invoked as:
|
||||
* <pre> $tabs = WFTabs::getInstance();</pre>
|
||||
*
|
||||
* @return object WFTabs
|
||||
*/
|
||||
public static function getInstance($config = array())
|
||||
{
|
||||
static $instance;
|
||||
|
||||
if (!is_object($instance)) {
|
||||
$instance = new self($config);
|
||||
}
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a template path.
|
||||
*
|
||||
* @param string $path
|
||||
*/
|
||||
public function addTemplatePath($path)
|
||||
{
|
||||
$this->_paths[] = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a panel view.
|
||||
*
|
||||
* @param object $layout Layout (panel) name
|
||||
*
|
||||
* @return panel JView object
|
||||
*/
|
||||
private function loadPanel($panel, $state)
|
||||
{
|
||||
$view = new WFView(array(
|
||||
'name' => $panel,
|
||||
'layout' => $panel,
|
||||
));
|
||||
|
||||
// add tab paths
|
||||
foreach ($this->_paths as $path) {
|
||||
$view->addTemplatePath($path);
|
||||
}
|
||||
|
||||
// assign panel state to view
|
||||
$view->state = (int) $state;
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
public function getPanel($panel)
|
||||
{
|
||||
if (array_key_exists($panel, $this->_panels)) {
|
||||
return $this->_panels[$panel];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a tab to the document. A panel is automatically created and assigned.
|
||||
*
|
||||
* @param object $tab Tab name
|
||||
* @param int $state Tab state (active or inactive)
|
||||
* @param array $values An array of values to assign to panel view
|
||||
*/
|
||||
public function addTab($tab, $state = 1, $values = array())
|
||||
{
|
||||
if (!array_key_exists($tab, $this->_tabs)) {
|
||||
$this->_tabs[$tab] = (int) $state === 1 ? $tab : '';
|
||||
|
||||
$panel = $this->addPanel($tab, $state);
|
||||
|
||||
// array is not empty and is associative
|
||||
if (!empty($values) && array_values($values) !== $values) {
|
||||
foreach($values as $key => $value) {
|
||||
$panel->$key = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a panel to the document.
|
||||
*
|
||||
* @param object $panel Panel name
|
||||
*/
|
||||
public function addPanel($tab, $state)
|
||||
{
|
||||
if (!array_key_exists($tab, $this->_panels)) {
|
||||
$this->_panels[$tab] = $this->loadPanel($tab, $state);
|
||||
|
||||
return $this->_panels[$tab];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a tab from the document.
|
||||
*
|
||||
* @param object $tab Tab name
|
||||
*/
|
||||
public function removeTab($tab)
|
||||
{
|
||||
if (array_key_exists($tab, $this->_tabs)) {
|
||||
unset($this->_tabs[$tab]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the document tabs and panels.
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
$output = '';
|
||||
|
||||
if (!empty($this->_tabs)) {
|
||||
$output .= '<div id="tabs">';
|
||||
}
|
||||
|
||||
// add tabs
|
||||
if (count($this->_tabs) > 1) {
|
||||
$output .= '<ul class="uk-tab" role="tablist">' . "\n";
|
||||
|
||||
$x = 0;
|
||||
|
||||
foreach ($this->_tabs as $name => $tab) {
|
||||
$class = '';
|
||||
|
||||
if ($x === 0) {
|
||||
$class .= ' uk-active';
|
||||
}
|
||||
|
||||
if (!$tab) {
|
||||
$class .= ' uk-hidden';
|
||||
}
|
||||
|
||||
$output .= "\t" . '<li role="presentation" aria-selected="false" class="' . $class . '"><button type="button" class="uk-button uk-button-link uk-button-tab" tabindex="-1" value="' . $name . '">' . JText::_('WF_TAB_' . strtoupper($name)) . '</button></li>' . "\n";
|
||||
++$x;
|
||||
}
|
||||
|
||||
$output .= "</ul>\n";
|
||||
}
|
||||
|
||||
// add panels
|
||||
if (!empty($this->_panels)) {
|
||||
$x = 0;
|
||||
|
||||
$output .= '<div class="uk-switcher">';
|
||||
|
||||
foreach ($this->_panels as $key => $panel) {
|
||||
$class = '';
|
||||
|
||||
if ($panel->state === 0) {
|
||||
$class .= ' uk-hidden';
|
||||
}
|
||||
|
||||
if (!empty($this->_tabs)) {
|
||||
if ($x === 0) {
|
||||
$class .= ' uk-active';
|
||||
} else {
|
||||
$class .= ' uk-tabs-hide';
|
||||
}
|
||||
}
|
||||
|
||||
$output .= '<div id="' . $key . '_tab" class="' . $class . '" role="tabpanel" aria-hidden="true">';
|
||||
$output .= $panel->loadTemplate();
|
||||
$output .= '</div>';
|
||||
|
||||
++$x;
|
||||
}
|
||||
|
||||
$output .= '</div>';
|
||||
}
|
||||
|
||||
// add closing div
|
||||
if (!empty($this->_tabs)) {
|
||||
$output .= "</div>\n";
|
||||
}
|
||||
|
||||
echo $output;
|
||||
}
|
||||
}
|
||||
24
components/com_jce/editor/libraries/classes/text.php
Normal file
24
components/com_jce/editor/libraries/classes/text.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die('RESTRICTED');
|
||||
|
||||
abstract class WFText
|
||||
{
|
||||
public static function _($string, $default = '')
|
||||
{
|
||||
return JText::_($string);
|
||||
}
|
||||
|
||||
public static function sprintf($string)
|
||||
{
|
||||
return JText::sprintf($string);
|
||||
}
|
||||
}
|
||||
787
components/com_jce/editor/libraries/classes/utility.php
Normal file
787
components/com_jce/editor/libraries/classes/utility.php
Normal file
@@ -0,0 +1,787 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die('RESTRICTED');
|
||||
|
||||
/* Set internal character encoding to UTF-8 */
|
||||
if (function_exists('mb_internal_encoding')) {
|
||||
mb_internal_encoding("UTF-8");
|
||||
}
|
||||
|
||||
abstract class WFUtility
|
||||
{
|
||||
/**
|
||||
* Multi-byte-safe pathinfo replacement.
|
||||
* Drop-in replacement for pathinfo(), but multibyte- and cross-platform-safe.
|
||||
*
|
||||
* From PHPMailer - https://github.com/PHPMailer/PHPMailer/blob/v6.1.4/src/PHPMailer.php#L4256-L4302
|
||||
*
|
||||
* @see http://www.php.net/manual/en/function.pathinfo.php#107461
|
||||
*
|
||||
* @param string $path A filename or path, does not need to exist as a file
|
||||
* @param int|string $options Either a PATHINFO_* constant,
|
||||
* or a string name to return only the specified piece
|
||||
*
|
||||
* @return string|array
|
||||
*/
|
||||
public static function mb_pathinfo($path, $options = null)
|
||||
{
|
||||
// check if multibyte string, use pathname() if not
|
||||
if (function_exists('mb_strlen')) {
|
||||
if (mb_strlen($path) === strlen($path)) {
|
||||
return pathinfo($path, $options);
|
||||
}
|
||||
}
|
||||
|
||||
$ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => '');
|
||||
|
||||
$pathinfo = array();
|
||||
|
||||
if (preg_match('#^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^.\\\\/]+?)|))[\\\\/.]*$#m', $path, $pathinfo)) {
|
||||
if (array_key_exists(1, $pathinfo)) {
|
||||
$ret['dirname'] = $pathinfo[1];
|
||||
}
|
||||
if (array_key_exists(2, $pathinfo)) {
|
||||
$ret['basename'] = $pathinfo[2];
|
||||
}
|
||||
if (array_key_exists(5, $pathinfo)) {
|
||||
$ret['extension'] = $pathinfo[5];
|
||||
}
|
||||
if (array_key_exists(3, $pathinfo)) {
|
||||
$ret['filename'] = $pathinfo[3];
|
||||
}
|
||||
}
|
||||
|
||||
switch ($options) {
|
||||
case PATHINFO_DIRNAME:
|
||||
case 'dirname':
|
||||
return $ret['dirname'];
|
||||
case PATHINFO_BASENAME:
|
||||
case 'basename':
|
||||
return $ret['basename'];
|
||||
case PATHINFO_EXTENSION:
|
||||
case 'extension':
|
||||
return $ret['extension'];
|
||||
case PATHINFO_FILENAME:
|
||||
case 'filename':
|
||||
return $ret['filename'];
|
||||
default:
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file extension from a path
|
||||
*
|
||||
* @param string $path The file path
|
||||
* @return string The file extension
|
||||
*/
|
||||
public static function getExtension($path)
|
||||
{
|
||||
$dot = strrpos($path, '.') + 1;
|
||||
return substr($path, $dot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the extension from a file name or path
|
||||
*
|
||||
* @param string $path The file path
|
||||
* @return string The file path without the extension
|
||||
*/
|
||||
public static function stripExtension($path)
|
||||
{
|
||||
return preg_replace('#\.[^.]*$#', '', $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file name
|
||||
*
|
||||
* @param string $path The file path
|
||||
* @return string The file name without the path or extension
|
||||
*/
|
||||
public static function getFilename($path)
|
||||
{
|
||||
// check if multibyte string, use basename() if not
|
||||
if (function_exists('mb_strlen')) {
|
||||
if (mb_strlen($path) === strlen($path)) {
|
||||
return pathinfo($path, PATHINFO_FILENAME);
|
||||
}
|
||||
}
|
||||
// get basename
|
||||
$path = self::mb_basename($path);
|
||||
|
||||
// remove name without extension
|
||||
return self::stripExtension($path);
|
||||
}
|
||||
|
||||
public static function cleanPath($path, $ds = DIRECTORY_SEPARATOR, $prefix = '')
|
||||
{
|
||||
$path = trim(rawurldecode($path));
|
||||
|
||||
// check for UNC path on IIS and set prefix
|
||||
if ($ds == '\\' && strlen($path) > 1) {
|
||||
if ($path[0] == '\\' && $path[1] == '\\') {
|
||||
$prefix = '\\';
|
||||
}
|
||||
}
|
||||
|
||||
// clean path, removing double slashes, replacing back/forward slashes with DIRECTORY_SEPARATOR
|
||||
$path = preg_replace('#[/\\\\]+#', $ds, $path);
|
||||
|
||||
// return path with prefix if any
|
||||
return $prefix . $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a DIRECTORY_SEPARATOR to the path if required.
|
||||
*
|
||||
* @param string $path the path
|
||||
* @param string $ds optional directory seperator
|
||||
*
|
||||
* @return string path with trailing DIRECTORY_SEPARATOR
|
||||
*/
|
||||
public static function fixPath($path, $ds = DIRECTORY_SEPARATOR)
|
||||
{
|
||||
return self::cleanPath($path . $ds);
|
||||
}
|
||||
|
||||
private static function checkCharValue($string)
|
||||
{
|
||||
// null byte check
|
||||
if (strstr($string, "\x00")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match('#([^\w\.\-\/\\\\\s ])#i', $string, $matches)) {
|
||||
foreach ($matches as $match) {
|
||||
// not a safe UTF-8 character
|
||||
if (ord($match) < 127) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function checkPath($path)
|
||||
{
|
||||
$path = urldecode($path);
|
||||
|
||||
if (self::checkCharValue($path) === false || strpos($path, '..') !== false) {
|
||||
throw new InvalidArgumentException('Invalid path');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Concat two paths together. Basically $a + $b.
|
||||
*
|
||||
* @param string $a path one
|
||||
* @param string $b path two
|
||||
* @param string $ds optional directory seperator
|
||||
*
|
||||
* @return string $a DIRECTORY_SEPARATOR $b
|
||||
*/
|
||||
public static function makePath($a, $b, $ds = DIRECTORY_SEPARATOR)
|
||||
{
|
||||
return self::cleanPath($a . $ds . $b, $ds);
|
||||
}
|
||||
|
||||
private static function utf8_latin_to_ascii($subject)
|
||||
{
|
||||
static $CHARS = null;
|
||||
|
||||
if (is_null($CHARS)) {
|
||||
$CHARS = array(
|
||||
'À' => 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Ä' => 'A', 'Å' => 'A', 'Æ' => 'AE',
|
||||
'Ç' => 'C', 'È' => 'E', 'É' => 'E', 'Ê' => 'E', 'Ë' => 'E', 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I', 'Ï' => 'I',
|
||||
'Ð' => 'D', 'Ñ' => 'N', 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O', 'Õ' => 'O', 'Ö' => 'O', 'Ø' => 'O',
|
||||
'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ü' => 'U', 'Ý' => 'Y', 'ß' => 's',
|
||||
'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' => 'a', 'å' => 'a', 'æ' => 'ae',
|
||||
'ç' => 'c', 'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e', 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i',
|
||||
'ñ' => 'n', 'ò' => 'o', 'ó' => 'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'o', 'ø' => 'o', 'ù' => 'u', 'ú' => 'u', 'û' => 'u', 'ü' => 'u',
|
||||
'ý' => 'y', 'ÿ' => 'y', 'Ā' => 'A', 'ā' => 'a', 'Ă' => 'A', 'ă' => 'a', 'Ą' => 'A', 'ą' => 'a',
|
||||
'Ć' => 'C', 'ć' => 'c', 'Ĉ' => 'C', 'ĉ' => 'c', 'Ċ' => 'C', 'ċ' => 'c', 'Č' => 'C', 'č' => 'c', 'Ď' => 'D', 'ď' => 'd', 'Đ' => 'D', 'đ' => 'd',
|
||||
'Ē' => 'E', 'ē' => 'e', 'Ĕ' => 'E', 'ĕ' => 'e', 'Ė' => 'E', 'ė' => 'e', 'Ę' => 'E', 'ę' => 'e', 'Ě' => 'E', 'ě' => 'e',
|
||||
'Ĝ' => 'G', 'ĝ' => 'g', 'Ğ' => 'G', 'ğ' => 'g', 'Ġ' => 'G', 'ġ' => 'g', 'Ģ' => 'G', 'ģ' => 'g', 'Ĥ' => 'H', 'ĥ' => 'h', 'Ħ' => 'H', 'ħ' => 'h',
|
||||
'Ĩ' => 'I', 'ĩ' => 'i', 'Ī' => 'I', 'ī' => 'i', 'Ĭ' => 'I', 'ĭ' => 'i', 'Į' => 'I', 'į' => 'i', 'İ' => 'I', 'ı' => 'i',
|
||||
'IJ' => 'IJ', 'ij' => 'ij', 'Ĵ' => 'J', 'ĵ' => 'j', 'Ķ' => 'K', 'ķ' => 'k', 'Ĺ' => 'L', 'ĺ' => 'l', 'Ļ' => 'L', 'ļ' => 'l', 'Ľ' => 'L', 'ľ' => 'l', 'Ŀ' => 'L', 'ŀ' => 'l', 'Ł' => 'l', 'ł' => 'l',
|
||||
'Ń' => 'N', 'ń' => 'n', 'Ņ' => 'N', 'ņ' => 'n', 'Ň' => 'N', 'ň' => 'n', 'ʼn' => 'n', 'Ō' => 'O', 'ō' => 'o', 'Ŏ' => 'O', 'ŏ' => 'o', 'Ő' => 'O', 'ő' => 'o', 'Œ' => 'OE', 'œ' => 'oe',
|
||||
'Ŕ' => 'R', 'ŕ' => 'r', 'Ŗ' => 'R', 'ŗ' => 'r', 'Ř' => 'R', 'ř' => 'r', 'Ś' => 'S', 'ś' => 's', 'Ŝ' => 'S', 'ŝ' => 's', 'Ş' => 'S', 'ş' => 's', 'Š' => 'S', 'š' => 's',
|
||||
'Ţ' => 'T', 'ţ' => 't', 'Ť' => 'T', 'ť' => 't', 'Ŧ' => 'T', 'ŧ' => 't', 'Ũ' => 'U', 'ũ' => 'u', 'Ū' => 'U', 'ū' => 'u', 'Ŭ' => 'U', 'ŭ' => 'u', 'Ů' => 'U', 'ů' => 'u', 'Ű' => 'U', 'ű' => 'u', 'Ų' => 'U', 'ų' => 'u',
|
||||
'Ŵ' => 'W', 'ŵ' => 'w', 'Ŷ' => 'Y', 'ŷ' => 'y', 'Ÿ' => 'Y', 'Ź' => 'Z', 'ź' => 'z', 'Ż' => 'Z', 'ż' => 'z', 'Ž' => 'Z', 'ž' => 'z', 'ſ' => 's', 'ƒ' => 'f', 'Ơ' => 'O', 'ơ' => 'o', 'Ư' => 'U', 'ư' => 'u',
|
||||
'Ǎ' => 'A', 'ǎ' => 'a', 'Ǐ' => 'I', 'ǐ' => 'i', 'Ǒ' => 'O', 'ǒ' => 'o', 'Ǔ' => 'U', 'ǔ' => 'u', 'Ǖ' => 'U', 'ǖ' => 'u', 'Ǘ' => 'U', 'ǘ' => 'u', 'Ǚ' => 'U', 'ǚ' => 'u', 'Ǜ' => 'U', 'ǜ' => 'u',
|
||||
'Ǻ' => 'A', 'ǻ' => 'a', 'Ǽ' => 'AE', 'ǽ' => 'ae', 'Ǿ' => 'O', 'ǿ' => 'o',
|
||||
);
|
||||
}
|
||||
|
||||
if (function_exists('transliterator_transliterate')) {
|
||||
if (is_array($subject)) {
|
||||
/*array_walk($subject, function (&$string) {
|
||||
$string = WFUtility::utf8_latin_to_ascii($string);
|
||||
});*/
|
||||
|
||||
for ($i = 0; $i < count($subject); $i++) {
|
||||
$subject[$i] = WFUtility::utf8_latin_to_ascii($subject[$i]);
|
||||
}
|
||||
|
||||
return $subject;
|
||||
}
|
||||
|
||||
$transformed = transliterator_transliterate('Any-Latin; Latin-ASCII;', $subject);
|
||||
|
||||
if ($transformed !== false) {
|
||||
return $transformed;
|
||||
}
|
||||
|
||||
return str_replace(array_keys($CHARS), array_values($CHARS), $subject);
|
||||
}
|
||||
|
||||
return str_replace(array_keys($CHARS), array_values($CHARS), $subject);
|
||||
}
|
||||
|
||||
protected static function changeCase($string, $case)
|
||||
{
|
||||
if (!function_exists('mb_strtolower') || !function_exists('mb_strtoupper')) {
|
||||
return $string;
|
||||
}
|
||||
|
||||
if (is_array($string)) {
|
||||
for ($i = 0; $i < count($string); $i++) {
|
||||
$string[$i] = WFUtility::changeCase($string[$i], $case);
|
||||
}
|
||||
} else {
|
||||
switch ($case) {
|
||||
case 'lowercase':
|
||||
$string = mb_strtolower($string);
|
||||
break;
|
||||
case 'uppercase':
|
||||
$string = mb_strtoupper($string);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
private static function cleanUTF8($string)
|
||||
{
|
||||
// remove some common characters
|
||||
$string = preg_replace('#[\+\\\/\?\#%&<>"\'=\[\]\{\},;@\^\(\)£€$~]#', '', $string);
|
||||
|
||||
$result = '';
|
||||
$length = strlen($string);
|
||||
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$char = $string[$i];
|
||||
|
||||
// only process on possible restricted characters or utf-8 letters/numbers
|
||||
if (preg_match('#[^\w\.\-\s ]#', $char)) {
|
||||
// skip any character less than 127, eg: &?@* etc.
|
||||
if (ord($char) < 127) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$result .= $char;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes file name safe to use.
|
||||
*
|
||||
* @param mixed The name of the file (not full path)
|
||||
*
|
||||
* @return mixed The sanitised string or array
|
||||
*/
|
||||
public static function makeSafe($subject, $mode = 'utf-8', $spaces = '_', $case = '')
|
||||
{
|
||||
$search = array();
|
||||
|
||||
// set default mode if none is passed in
|
||||
if (empty($mode)) {
|
||||
$mode = 'utf-8';
|
||||
}
|
||||
|
||||
if (!function_exists('mb_internal_encoding')) {
|
||||
$mode = 'ascii';
|
||||
}
|
||||
|
||||
// trim
|
||||
if (is_array($subject)) {
|
||||
$subject = array_map('trim', $subject);
|
||||
} else {
|
||||
$subject = trim($subject);
|
||||
}
|
||||
|
||||
// replace spaces with specified character or space
|
||||
if (is_string($spaces)) {
|
||||
$subject = preg_replace('#[\s ]+#', $spaces, $subject);
|
||||
}
|
||||
|
||||
if ($mode === 'utf-8') {
|
||||
$search[] = '#[^\pL\pM\pN_\.\-\s ]#u';
|
||||
} else {
|
||||
$subject = self::utf8_latin_to_ascii($subject);
|
||||
$search[] = '#[^a-zA-Z0-9_\.\-\s ]#';
|
||||
}
|
||||
|
||||
// remove multiple . characters
|
||||
$search[] = '#(\.){2,}#';
|
||||
|
||||
// strip leading period
|
||||
$search[] = '#^\.#';
|
||||
|
||||
// strip trailing period
|
||||
$search[] = '#\.$#';
|
||||
|
||||
// strip whitespace
|
||||
$search[] = '#^\s*|\s*$#';
|
||||
|
||||
// only for utf-8 to avoid PCRE errors - PCRE must be at least version 5
|
||||
if ($mode == 'utf-8') {
|
||||
try {
|
||||
// perform pcre replacement
|
||||
$result = preg_replace($search, '', $subject);
|
||||
} catch (Exception $e) {
|
||||
// try ascii
|
||||
return self::makeSafe($subject, 'ascii');
|
||||
}
|
||||
|
||||
// try ascii
|
||||
if (is_null($result) || $result === false) {
|
||||
return self::makeSafe($subject, 'ascii');
|
||||
}
|
||||
|
||||
if ($case) {
|
||||
// change case
|
||||
$result = self::changeCase($result, $case);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result = preg_replace($search, '', $subject);
|
||||
|
||||
if ($case) {
|
||||
// change case
|
||||
$result = self::changeCase($result, $case);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the file size, limits to Mb.
|
||||
*
|
||||
* @param int $size the raw filesize
|
||||
*
|
||||
* @return string formated file size
|
||||
*/
|
||||
public static function formatSize($size)
|
||||
{
|
||||
if ($size < 1024) {
|
||||
return $size . ' ' . WFText::_('WF_LABEL_BYTES');
|
||||
} elseif ($size >= 1024 && $size < 1024 * 1024) {
|
||||
return sprintf('%01.2f', $size / 1024.0) . ' ' . WFText::_('WF_LABEL_KB');
|
||||
} else {
|
||||
return sprintf('%01.2f', $size / (1024.0 * 1024)) . ' ' . WFText::_('WF_LABEL_MB');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the date.
|
||||
*
|
||||
* @param int $date the unix datestamp
|
||||
*
|
||||
* @return string formated date
|
||||
*/
|
||||
public static function formatDate($date, $format = '%d/%m/%Y, %H:%M')
|
||||
{
|
||||
return strftime($format, $date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the modified date of a file.
|
||||
*
|
||||
* @return Formatted modified date
|
||||
*
|
||||
* @param string $file Absolute path to file
|
||||
*/
|
||||
public static function getDate($file)
|
||||
{
|
||||
return self::formatDate(@filemtime($file));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size of a file.
|
||||
*
|
||||
* @return Formatted filesize value
|
||||
*
|
||||
* @param string $file Absolute path to file
|
||||
*/
|
||||
public static function getSize($file)
|
||||
{
|
||||
return self::formatSize(@filesize($file));
|
||||
}
|
||||
|
||||
/**
|
||||
* Multi-byte-safe dirname replacement.
|
||||
* https://gist.github.com/tcyrus/257a1ed93c5e115b7b33426d029b5c5f
|
||||
*
|
||||
* @param string $path A Path
|
||||
* @param int $levels The number of parent directories to go up.
|
||||
* @return string The path of a parent directory.
|
||||
*/
|
||||
public static function mb_dirname($path)
|
||||
{
|
||||
// check if multibyte string, use dirname() if not
|
||||
if (function_exists('mb_strlen')) {
|
||||
if (mb_strlen($path) === strlen($path)) {
|
||||
return dirname($path);
|
||||
}
|
||||
}
|
||||
|
||||
// clean
|
||||
$path = self::cleanPath($path, '/');
|
||||
|
||||
// get last slash position
|
||||
$slash = strrpos($path, '/') + 1;
|
||||
|
||||
// return dirname
|
||||
return substr($path, 0, $slash);
|
||||
}
|
||||
|
||||
public static function mb_basename($path, $ext = '')
|
||||
{
|
||||
// check if multibyte string, use basename() if not
|
||||
if (function_exists('mb_strlen')) {
|
||||
if (mb_strlen($path) === strlen($path)) {
|
||||
return basename($path, $ext);
|
||||
}
|
||||
}
|
||||
|
||||
// clean
|
||||
$path = self::cleanPath($path, '/');
|
||||
|
||||
// split path
|
||||
$parts = explode('/', $path);
|
||||
|
||||
// return basename
|
||||
$path = end($parts);
|
||||
|
||||
if ($ext === '.' . self::getExtension($path)) {
|
||||
$path = self::stripExtension($path);
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
public static function convertEncoding($string)
|
||||
{
|
||||
if (!function_exists('mb_detect_encoding')) {
|
||||
// From http://w3.org/International/questions/qa-forms-utf-8.html
|
||||
$isUTF8 = preg_match('%^(?:
|
||||
[\x09\x0A\x0D\x20-\x7E] # ASCII
|
||||
| [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
|
||||
| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
|
||||
| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
|
||||
| \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
|
||||
| \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
|
||||
| [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
|
||||
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
|
||||
)*$%xs', $string);
|
||||
|
||||
if (!$isUTF8) {
|
||||
return utf8_encode($string);
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
// get encoding
|
||||
$encoding = mb_detect_encoding($string, "auto", true);
|
||||
|
||||
// return existing string if it is already utf-8
|
||||
if ($encoding === 'UTF-8') {
|
||||
return $string;
|
||||
}
|
||||
|
||||
// invalid encoding, so make a "safe" string
|
||||
if ($encoding === false) {
|
||||
return preg_replace('#[^a-zA-Z0-9_\.\-\s ]#', '', $string);
|
||||
}
|
||||
|
||||
// convert to utf-8 and return
|
||||
return mb_convert_encoding($string, 'UTF-8', $encoding);
|
||||
}
|
||||
|
||||
public static function isUtf8($string)
|
||||
{
|
||||
if (!function_exists('mb_detect_encoding')) {
|
||||
// From http://w3.org/International/questions/qa-forms-utf-8.html
|
||||
return preg_match('%^(?:
|
||||
[\x09\x0A\x0D\x20-\x7E] # ASCII
|
||||
| [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
|
||||
| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
|
||||
| [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
|
||||
| \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
|
||||
| \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
|
||||
| [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
|
||||
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
|
||||
)*$%xs', $string);
|
||||
}
|
||||
|
||||
return mb_detect_encoding($string, 'UTF-8', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert size value to bytes.
|
||||
*/
|
||||
public static function convertSize($value)
|
||||
{
|
||||
$unit = '';
|
||||
|
||||
preg_match('#([0-9]+)\s?([a-z]*)#i', $value, $matches);
|
||||
|
||||
if (isset($matches[1])) {
|
||||
$value = (int) $matches[1];
|
||||
}
|
||||
|
||||
if (isset($matches[2])) {
|
||||
$unit = $matches[2];
|
||||
|
||||
// extract first character only, eg: g, m, k
|
||||
if ($unit) {
|
||||
$unit = strtolower($unit[0]);
|
||||
}
|
||||
}
|
||||
|
||||
$value = intval($value);
|
||||
|
||||
// Convert to bytes
|
||||
switch ($unit) {
|
||||
case 'g':
|
||||
$value = $value * 1073741824;
|
||||
break;
|
||||
case 'm':
|
||||
$value = $value * 1048576;
|
||||
break;
|
||||
case 'k':
|
||||
$value = $value * 1024;
|
||||
break;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks an upload for suspicious naming, potential PHP contents, valid image and HTML tags.
|
||||
*/
|
||||
public static function isSafeFile($file)
|
||||
{
|
||||
// null byte check
|
||||
if (strstr($file['name'], "\x00")) {
|
||||
@unlink($file['tmp_name']);
|
||||
throw new InvalidArgumentException('The file name contains a null byte.');
|
||||
}
|
||||
|
||||
// check name for invalid extensions
|
||||
if (self::validateFileName($file['name']) !== true) {
|
||||
@unlink($file['tmp_name']);
|
||||
throw new InvalidArgumentException('The file name contains an invalid extension.');
|
||||
}
|
||||
|
||||
$isImage = preg_match('#\.(jpeg|jpg|jpe|png|gif|wbmp|bmp|tiff|tif|webp|psd|swc|iff|jpc|jp2|jpx|jb2|xbm|ico|xcf|odg)$#i', $file['name']);
|
||||
|
||||
// check file for <?php tags
|
||||
$fp = @fopen($file['tmp_name'], 'r');
|
||||
|
||||
if ($fp !== false) {
|
||||
$data = '';
|
||||
|
||||
while (!feof($fp)) {
|
||||
$data .= @fread($fp, 131072);
|
||||
// we can only reliably check for the full <?php tag here (short tags conflict with valid exif xml data), so users are reminded to disable short_open_tag
|
||||
if (stripos($data, '<?php') !== false) {
|
||||
@unlink($file['tmp_name']);
|
||||
throw new InvalidArgumentException('The file contains PHP code.');
|
||||
}
|
||||
|
||||
// check for `__HALT_COMPILER()` phar stub
|
||||
if (stripos($data, '__HALT_COMPILER()') !== false) {
|
||||
@unlink($file['tmp_name']);
|
||||
throw new InvalidArgumentException('The file contains PHP code.');
|
||||
}
|
||||
|
||||
$data = substr($data, -10);
|
||||
}
|
||||
|
||||
fclose($fp);
|
||||
}
|
||||
|
||||
// validate image
|
||||
if ($isImage && @getimagesize($file['tmp_name']) === false) {
|
||||
@unlink($file['tmp_name']);
|
||||
throw new InvalidArgumentException('The file is not a valid image.');
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check file name for extensions.
|
||||
*
|
||||
* @param type $name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function validateFileName($name)
|
||||
{
|
||||
if (empty($name) && (string) $name !== "0") {
|
||||
return false;
|
||||
}
|
||||
|
||||
// list of invalid extensions
|
||||
$executable = array(
|
||||
'php', 'php3', 'php4', 'php5', 'php6', 'php7', 'phar', 'js', 'exe', 'phtml', 'java', 'perl', 'py', 'asp', 'dll', 'go', 'ade', 'adp', 'bat', 'chm', 'cmd', 'com', 'cpl', 'hta', 'ins', 'isp',
|
||||
'jse', 'lib', 'mde', 'msc', 'msp', 'mst', 'pif', 'scr', 'sct', 'shb', 'sys', 'vb', 'vbe', 'vbs', 'vxd', 'wsc', 'wsf', 'wsh', 'svg',
|
||||
);
|
||||
|
||||
// get file parts, eg: ['image', 'php', 'jpg']
|
||||
$parts = explode('.', $name);
|
||||
|
||||
// remove extension
|
||||
array_pop($parts);
|
||||
|
||||
// remove name
|
||||
array_shift($parts);
|
||||
|
||||
// no extensions in file name
|
||||
if (empty($parts)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// lowercase it
|
||||
array_map('strtolower', $parts);
|
||||
|
||||
// check for extension in file name, eg: image.php.jpg
|
||||
foreach ($executable as $extension) {
|
||||
if (in_array($extension, $parts)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to determine if an array is an associative array.
|
||||
*
|
||||
* @param array An array to test
|
||||
*
|
||||
* @return bool True if the array is an associative array
|
||||
*
|
||||
* @link https://www.php.net/manual/en/function.is-array.php#84488
|
||||
*/
|
||||
public static function is_associative_array($array)
|
||||
{
|
||||
if (!is_array($array)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$i = count($array);
|
||||
|
||||
while ($i > 0) {
|
||||
if (!array_key_exists(--$i, $array)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function isJson($value)
|
||||
{
|
||||
// value must be a string
|
||||
if (!$value || !is_string($value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// trim
|
||||
$value = trim($value);
|
||||
|
||||
if (!$value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// quick syntax check
|
||||
if ($value[0] !== '{' && $value[0] !== '[') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// full check using json_decode
|
||||
json_decode($value);
|
||||
return json_last_error() == JSON_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* array_merge_recursive does indeed merge arrays, but it converts values with duplicate
|
||||
* keys to arrays rather than overwriting the value in the first array with the duplicate
|
||||
* value in the second array, as array_merge does. I.e., with array_merge_recursive,
|
||||
* this happens (documented behavior):.
|
||||
*
|
||||
* array_merge_recursive(array('key' => 'org value'), array('key' => 'new value'));
|
||||
* => array('key' => array('org value', 'new value'));
|
||||
*
|
||||
* array_merge_recursive_distinct does not change the datatypes of the values in the arrays.
|
||||
* Matching keys' values in the second array overwrite those in the first array, as is the
|
||||
* case with array_merge, i.e.:
|
||||
*
|
||||
* array_merge_recursive_distinct(array('key' => 'org value'), array('key' => 'new value'));
|
||||
* => array('key' => array('new value'));
|
||||
*
|
||||
* Parameters are passed by reference, though only for performance reasons. They're not
|
||||
* altered by this function.
|
||||
*
|
||||
* @param array $array1
|
||||
* @param array $array2
|
||||
* @param boolean $ignore_empty_string
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @author Daniel <daniel (at) danielsmedegaardbuus (dot) dk>
|
||||
* @author Gabriel Sobrinho <gabriel (dot) sobrinho (at) gmail (dot) com>
|
||||
*/
|
||||
public static function array_merge_recursive_distinct(array $array1, array $array2, $ignore_empty_string = false)
|
||||
{
|
||||
$merged = $array1;
|
||||
|
||||
foreach ($array2 as $key => $value) {
|
||||
if (self::is_associative_array($value) && array_key_exists($key, $merged) && self::is_associative_array($merged[$key])) {
|
||||
$merged[$key] = self::array_merge_recursive_distinct($merged[$key], $value, $ignore_empty_string);
|
||||
} else {
|
||||
if (is_null($value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (array_key_exists($key, $merged) && $ignore_empty_string && $value === "") {
|
||||
continue;
|
||||
}
|
||||
|
||||
$merged[$key] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $merged;
|
||||
}
|
||||
}
|
||||
10
components/com_jce/editor/libraries/classes/vendor/cssmin/cssmin.php
vendored
Normal file
10
components/com_jce/editor/libraries/classes/vendor/cssmin/cssmin.php
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
abstract class CssMin {
|
||||
public static function minify($text)
|
||||
{
|
||||
$compressor = new tubalmartin\CssMin\Minifier();
|
||||
|
||||
return $compressor->run($text);
|
||||
}
|
||||
}
|
||||
1
components/com_jce/editor/libraries/classes/vendor/cssmin/index.html
vendored
Normal file
1
components/com_jce/editor/libraries/classes/vendor/cssmin/index.html
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
||||
155
components/com_jce/editor/libraries/classes/vendor/cssmin/src/Colors.php
vendored
Normal file
155
components/com_jce/editor/libraries/classes/vendor/cssmin/src/Colors.php
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
namespace tubalmartin\CssMin;
|
||||
|
||||
class Colors
|
||||
{
|
||||
public static function getHexToNamedMap()
|
||||
{
|
||||
// Hex colors longer than named counterpart
|
||||
return array(
|
||||
'#f0ffff' => 'azure',
|
||||
'#f5f5dc' => 'beige',
|
||||
'#ffe4c4' => 'bisque',
|
||||
'#a52a2a' => 'brown',
|
||||
'#ff7f50' => 'coral',
|
||||
'#ffd700' => 'gold',
|
||||
'#808080' => 'gray',
|
||||
'#008000' => 'green',
|
||||
'#4b0082' => 'indigo',
|
||||
'#fffff0' => 'ivory',
|
||||
'#f0e68c' => 'khaki',
|
||||
'#faf0e6' => 'linen',
|
||||
'#800000' => 'maroon',
|
||||
'#000080' => 'navy',
|
||||
'#fdf5e6' => 'oldlace',
|
||||
'#808000' => 'olive',
|
||||
'#ffa500' => 'orange',
|
||||
'#da70d6' => 'orchid',
|
||||
'#cd853f' => 'peru',
|
||||
'#ffc0cb' => 'pink',
|
||||
'#dda0dd' => 'plum',
|
||||
'#800080' => 'purple',
|
||||
'#f00' => 'red',
|
||||
'#fa8072' => 'salmon',
|
||||
'#a0522d' => 'sienna',
|
||||
'#c0c0c0' => 'silver',
|
||||
'#fffafa' => 'snow',
|
||||
'#d2b48c' => 'tan',
|
||||
'#008080' => 'teal',
|
||||
'#ff6347' => 'tomato',
|
||||
'#ee82ee' => 'violet',
|
||||
'#f5deb3' => 'wheat'
|
||||
);
|
||||
}
|
||||
|
||||
public static function getNamedToHexMap()
|
||||
{
|
||||
// Named colors longer than hex counterpart
|
||||
return array(
|
||||
'aliceblue' => '#f0f8ff',
|
||||
'antiquewhite' => '#faebd7',
|
||||
'aquamarine' => '#7fffd4',
|
||||
'black' => '#000',
|
||||
'blanchedalmond' => '#ffebcd',
|
||||
'blueviolet' => '#8a2be2',
|
||||
'burlywood' => '#deb887',
|
||||
'cadetblue' => '#5f9ea0',
|
||||
'chartreuse' => '#7fff00',
|
||||
'chocolate' => '#d2691e',
|
||||
'cornflowerblue' => '#6495ed',
|
||||
'cornsilk' => '#fff8dc',
|
||||
'darkblue' => '#00008b',
|
||||
'darkcyan' => '#008b8b',
|
||||
'darkgoldenrod' => '#b8860b',
|
||||
'darkgray' => '#a9a9a9',
|
||||
'darkgreen' => '#006400',
|
||||
'darkgrey' => '#a9a9a9',
|
||||
'darkkhaki' => '#bdb76b',
|
||||
'darkmagenta' => '#8b008b',
|
||||
'darkolivegreen' => '#556b2f',
|
||||
'darkorange' => '#ff8c00',
|
||||
'darkorchid' => '#9932cc',
|
||||
'darksalmon' => '#e9967a',
|
||||
'darkseagreen' => '#8fbc8f',
|
||||
'darkslateblue' => '#483d8b',
|
||||
'darkslategray' => '#2f4f4f',
|
||||
'darkslategrey' => '#2f4f4f',
|
||||
'darkturquoise' => '#00ced1',
|
||||
'darkviolet' => '#9400d3',
|
||||
'deeppink' => '#ff1493',
|
||||
'deepskyblue' => '#00bfff',
|
||||
'dodgerblue' => '#1e90ff',
|
||||
'firebrick' => '#b22222',
|
||||
'floralwhite' => '#fffaf0',
|
||||
'forestgreen' => '#228b22',
|
||||
'fuchsia' => '#f0f',
|
||||
'gainsboro' => '#dcdcdc',
|
||||
'ghostwhite' => '#f8f8ff',
|
||||
'goldenrod' => '#daa520',
|
||||
'greenyellow' => '#adff2f',
|
||||
'honeydew' => '#f0fff0',
|
||||
'indianred' => '#cd5c5c',
|
||||
'lavender' => '#e6e6fa',
|
||||
'lavenderblush' => '#fff0f5',
|
||||
'lawngreen' => '#7cfc00',
|
||||
'lemonchiffon' => '#fffacd',
|
||||
'lightblue' => '#add8e6',
|
||||
'lightcoral' => '#f08080',
|
||||
'lightcyan' => '#e0ffff',
|
||||
'lightgoldenrodyellow' => '#fafad2',
|
||||
'lightgray' => '#d3d3d3',
|
||||
'lightgreen' => '#90ee90',
|
||||
'lightgrey' => '#d3d3d3',
|
||||
'lightpink' => '#ffb6c1',
|
||||
'lightsalmon' => '#ffa07a',
|
||||
'lightseagreen' => '#20b2aa',
|
||||
'lightskyblue' => '#87cefa',
|
||||
'lightslategray' => '#778899',
|
||||
'lightslategrey' => '#778899',
|
||||
'lightsteelblue' => '#b0c4de',
|
||||
'lightyellow' => '#ffffe0',
|
||||
'limegreen' => '#32cd32',
|
||||
'mediumaquamarine' => '#66cdaa',
|
||||
'mediumblue' => '#0000cd',
|
||||
'mediumorchid' => '#ba55d3',
|
||||
'mediumpurple' => '#9370db',
|
||||
'mediumseagreen' => '#3cb371',
|
||||
'mediumslateblue' => '#7b68ee',
|
||||
'mediumspringgreen' => '#00fa9a',
|
||||
'mediumturquoise' => '#48d1cc',
|
||||
'mediumvioletred' => '#c71585',
|
||||
'midnightblue' => '#191970',
|
||||
'mintcream' => '#f5fffa',
|
||||
'mistyrose' => '#ffe4e1',
|
||||
'moccasin' => '#ffe4b5',
|
||||
'navajowhite' => '#ffdead',
|
||||
'olivedrab' => '#6b8e23',
|
||||
'orangered' => '#ff4500',
|
||||
'palegoldenrod' => '#eee8aa',
|
||||
'palegreen' => '#98fb98',
|
||||
'paleturquoise' => '#afeeee',
|
||||
'palevioletred' => '#db7093',
|
||||
'papayawhip' => '#ffefd5',
|
||||
'peachpuff' => '#ffdab9',
|
||||
'powderblue' => '#b0e0e6',
|
||||
'rebeccapurple' => '#663399',
|
||||
'rosybrown' => '#bc8f8f',
|
||||
'royalblue' => '#4169e1',
|
||||
'saddlebrown' => '#8b4513',
|
||||
'sandybrown' => '#f4a460',
|
||||
'seagreen' => '#2e8b57',
|
||||
'seashell' => '#fff5ee',
|
||||
'slateblue' => '#6a5acd',
|
||||
'slategray' => '#708090',
|
||||
'slategrey' => '#708090',
|
||||
'springgreen' => '#00ff7f',
|
||||
'steelblue' => '#4682b4',
|
||||
'turquoise' => '#40e0d0',
|
||||
'white' => '#fff',
|
||||
'whitesmoke' => '#f5f5f5',
|
||||
'yellow' => '#ff0',
|
||||
'yellowgreen' => '#9acd32'
|
||||
);
|
||||
}
|
||||
}
|
||||
223
components/com_jce/editor/libraries/classes/vendor/cssmin/src/Command.php
vendored
Normal file
223
components/com_jce/editor/libraries/classes/vendor/cssmin/src/Command.php
vendored
Normal file
@@ -0,0 +1,223 @@
|
||||
<?php
|
||||
|
||||
namespace tubalmartin\CssMin;
|
||||
|
||||
class Command
|
||||
{
|
||||
const SUCCESS_EXIT = 0;
|
||||
const FAILURE_EXIT = 1;
|
||||
|
||||
protected $stats = array();
|
||||
|
||||
public static function main()
|
||||
{
|
||||
$command = new self;
|
||||
$command->run();
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
$opts = getopt(
|
||||
'hi:o:',
|
||||
array(
|
||||
'help',
|
||||
'input:',
|
||||
'output:',
|
||||
'dry-run',
|
||||
'keep-sourcemap',
|
||||
'keep-sourcemap-comment',
|
||||
'linebreak-position:',
|
||||
'memory-limit:',
|
||||
'pcre-backtrack-limit:',
|
||||
'pcre-recursion-limit:',
|
||||
'remove-important-comments'
|
||||
)
|
||||
);
|
||||
|
||||
$help = $this->getOpt(array('h', 'help'), $opts);
|
||||
$input = $this->getOpt(array('i', 'input'), $opts);
|
||||
$output = $this->getOpt(array('o', 'output'), $opts);
|
||||
$dryrun = $this->getOpt('dry-run', $opts);
|
||||
$keepSourceMapComment = $this->getOpt(array('keep-sourcemap', 'keep-sourcemap-comment'), $opts);
|
||||
$linebreakPosition = $this->getOpt('linebreak-position', $opts);
|
||||
$memoryLimit = $this->getOpt('memory-limit', $opts);
|
||||
$backtrackLimit = $this->getOpt('pcre-backtrack-limit', $opts);
|
||||
$recursionLimit = $this->getOpt('pcre-recursion-limit', $opts);
|
||||
$removeImportantComments = $this->getOpt('remove-important-comments', $opts);
|
||||
|
||||
if (!is_null($help)) {
|
||||
$this->showHelp();
|
||||
die(self::SUCCESS_EXIT);
|
||||
}
|
||||
|
||||
if (is_null($input)) {
|
||||
fwrite(STDERR, '-i <file> argument is missing' . PHP_EOL);
|
||||
$this->showHelp();
|
||||
die(self::FAILURE_EXIT);
|
||||
}
|
||||
|
||||
if (!is_readable($input)) {
|
||||
fwrite(STDERR, 'Input file is not readable' . PHP_EOL);
|
||||
die(self::FAILURE_EXIT);
|
||||
}
|
||||
|
||||
$css = file_get_contents($input);
|
||||
|
||||
if ($css === false) {
|
||||
fwrite(STDERR, 'Input CSS code could not be retrieved from input file' . PHP_EOL);
|
||||
die(self::FAILURE_EXIT);
|
||||
}
|
||||
|
||||
$this->setStat('original-size', strlen($css));
|
||||
|
||||
$cssmin = new Minifier;
|
||||
|
||||
if (!is_null($keepSourceMapComment)) {
|
||||
$cssmin->keepSourceMapComment();
|
||||
}
|
||||
|
||||
if (!is_null($removeImportantComments)) {
|
||||
$cssmin->removeImportantComments();
|
||||
}
|
||||
|
||||
if (!is_null($linebreakPosition)) {
|
||||
$cssmin->setLineBreakPosition($linebreakPosition);
|
||||
}
|
||||
|
||||
if (!is_null($memoryLimit)) {
|
||||
$cssmin->setMemoryLimit($memoryLimit);
|
||||
}
|
||||
|
||||
if (!is_null($backtrackLimit)) {
|
||||
$cssmin->setPcreBacktrackLimit($backtrackLimit);
|
||||
}
|
||||
|
||||
if (!is_null($recursionLimit)) {
|
||||
$cssmin->setPcreRecursionLimit($recursionLimit);
|
||||
}
|
||||
|
||||
$this->setStat('compression-time-start', microtime(true));
|
||||
|
||||
$css = $cssmin->run($css);
|
||||
|
||||
$this->setStat('compression-time-end', microtime(true));
|
||||
$this->setStat('peak-memory-usage', memory_get_peak_usage(true));
|
||||
$this->setStat('compressed-size', strlen($css));
|
||||
|
||||
if (!is_null($dryrun)) {
|
||||
$this->showStats();
|
||||
die(self::SUCCESS_EXIT);
|
||||
}
|
||||
|
||||
if (is_null($output)) {
|
||||
fwrite(STDOUT, $css . PHP_EOL);
|
||||
$this->showStats();
|
||||
die(self::SUCCESS_EXIT);
|
||||
}
|
||||
|
||||
if (!is_writable(dirname($output))) {
|
||||
fwrite(STDERR, 'Output file is not writable' . PHP_EOL);
|
||||
die(self::FAILURE_EXIT);
|
||||
}
|
||||
|
||||
if (file_put_contents($output, $css) === false) {
|
||||
fwrite(STDERR, 'Compressed CSS code could not be saved to output file' . PHP_EOL);
|
||||
die(self::FAILURE_EXIT);
|
||||
}
|
||||
|
||||
$this->showStats();
|
||||
|
||||
die(self::SUCCESS_EXIT);
|
||||
}
|
||||
|
||||
protected function getOpt($opts, $options)
|
||||
{
|
||||
$value = null;
|
||||
|
||||
if (is_string($opts)) {
|
||||
$opts = array($opts);
|
||||
}
|
||||
|
||||
foreach ($opts as $opt) {
|
||||
if (array_key_exists($opt, $options)) {
|
||||
$value = $options[$opt];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
protected function setStat($statName, $statValue)
|
||||
{
|
||||
$this->stats[$statName] = $statValue;
|
||||
}
|
||||
|
||||
protected function formatBytes($size, $precision = 2)
|
||||
{
|
||||
$base = log($size, 1024);
|
||||
$suffixes = array('B', 'K', 'M', 'G', 'T');
|
||||
return round(pow(1024, $base - floor($base)), $precision) .' '. $suffixes[floor($base)];
|
||||
}
|
||||
|
||||
protected function formatMicroSeconds($microSecs, $precision = 2)
|
||||
{
|
||||
// ms
|
||||
$time = round($microSecs * 1000, $precision);
|
||||
|
||||
if ($time >= 60 * 1000) {
|
||||
$time = round($time / 60 * 1000, $precision) .' m'; // m
|
||||
} elseif ($time >= 1000) {
|
||||
$time = round($time / 1000, $precision) .' s'; // s
|
||||
} else {
|
||||
$time .= ' ms';
|
||||
}
|
||||
|
||||
return $time;
|
||||
}
|
||||
|
||||
protected function showStats()
|
||||
{
|
||||
$spaceSavings = round((1 - ($this->stats['compressed-size'] / $this->stats['original-size'])) * 100, 2);
|
||||
$compressionRatio = round($this->stats['original-size'] / $this->stats['compressed-size'], 2);
|
||||
$compressionTime = $this->formatMicroSeconds(
|
||||
$this->stats['compression-time-end'] - $this->stats['compression-time-start']
|
||||
);
|
||||
$peakMemoryUsage = $this->formatBytes($this->stats['peak-memory-usage']);
|
||||
|
||||
print <<<EOT
|
||||
|
||||
------------------------------
|
||||
CSSMIN STATS
|
||||
------------------------------
|
||||
Space savings: {$spaceSavings} %
|
||||
Compression ratio: {$compressionRatio}:1
|
||||
Compression time: $compressionTime
|
||||
Peak memory usage: $peakMemoryUsage
|
||||
|
||||
|
||||
EOT;
|
||||
}
|
||||
|
||||
protected function showHelp()
|
||||
{
|
||||
print <<<'EOT'
|
||||
Usage: cssmin [options] -i <file> [-o <file>]
|
||||
|
||||
-i|--input <file> File containing uncompressed CSS code.
|
||||
-o|--output <file> File to use to save compressed CSS code.
|
||||
|
||||
Options:
|
||||
|
||||
-h|--help Prints this usage information.
|
||||
--dry-run Performs a dry run displaying statistics.
|
||||
--keep-sourcemap[-comment] Keeps the sourcemap special comment in the output.
|
||||
--linebreak-position <pos> Splits long lines after a specific column in the output.
|
||||
--memory-limit <limit> Sets the memory limit for this script.
|
||||
--pcre-backtrack-limit <limit> Sets the PCRE backtrack limit for this script.
|
||||
--pcre-recursion-limit <limit> Sets the PCRE recursion limit for this script.
|
||||
--remove-important-comments Removes !important comments from output.
|
||||
|
||||
EOT;
|
||||
}
|
||||
}
|
||||
895
components/com_jce/editor/libraries/classes/vendor/cssmin/src/Minifier.php
vendored
Normal file
895
components/com_jce/editor/libraries/classes/vendor/cssmin/src/Minifier.php
vendored
Normal file
@@ -0,0 +1,895 @@
|
||||
<?php
|
||||
|
||||
/*!
|
||||
* CssMin
|
||||
* Author: Tubal Martin - http://tubalmartin.me/
|
||||
* Repo: https://github.com/tubalmartin/YUI-CSS-compressor-PHP-port
|
||||
*
|
||||
* This is a PHP port of the CSS minification tool distributed with YUICompressor,
|
||||
* itself a port of the cssmin utility by Isaac Schlueter - http://foohack.com/
|
||||
* Permission is hereby granted to use the PHP version under the same
|
||||
* conditions as the YUICompressor.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* YUI Compressor
|
||||
* http://developer.yahoo.com/yui/compressor/
|
||||
* Author: Julien Lecomte - http://www.julienlecomte.net/
|
||||
* Copyright (c) 2013 Yahoo! Inc. All rights reserved.
|
||||
* The copyrights embodied in the content of this file are licensed
|
||||
* by Yahoo! Inc. under the BSD (revised) open source license.
|
||||
*/
|
||||
|
||||
namespace tubalmartin\CssMin;
|
||||
|
||||
class Minifier
|
||||
{
|
||||
const QUERY_FRACTION = '_CSSMIN_QF_';
|
||||
const COMMENT_TOKEN = '_CSSMIN_CMT_%d_';
|
||||
const COMMENT_TOKEN_START = '_CSSMIN_CMT_';
|
||||
const RULE_BODY_TOKEN = '_CSSMIN_RBT_%d_';
|
||||
const PRESERVED_TOKEN = '_CSSMIN_PTK_%d_';
|
||||
|
||||
// Token lists
|
||||
private $comments = array();
|
||||
private $ruleBodies = array();
|
||||
private $preservedTokens = array();
|
||||
|
||||
// Output options
|
||||
private $keepImportantComments = true;
|
||||
private $keepSourceMapComment = false;
|
||||
private $linebreakPosition = 0;
|
||||
|
||||
// PHP ini limits
|
||||
private $raisePhpLimits;
|
||||
private $memoryLimit;
|
||||
private $maxExecutionTime = 60; // 1 min
|
||||
private $pcreBacktrackLimit;
|
||||
private $pcreRecursionLimit;
|
||||
|
||||
// Color maps
|
||||
private $hexToNamedColorsMap;
|
||||
private $namedToHexColorsMap;
|
||||
|
||||
// Regexes
|
||||
private $numRegex;
|
||||
private $charsetRegex = '/@charset [^;]+;/Si';
|
||||
private $importRegex = '/@import [^;]+;/Si';
|
||||
private $namespaceRegex = '/@namespace [^;]+;/Si';
|
||||
private $namedToHexColorsRegex;
|
||||
private $shortenOneZeroesRegex;
|
||||
private $shortenTwoZeroesRegex;
|
||||
private $shortenThreeZeroesRegex;
|
||||
private $shortenFourZeroesRegex;
|
||||
private $unitsGroupRegex = '(?:ch|cm|em|ex|gd|in|mm|px|pt|pc|q|rem|vh|vmax|vmin|vw|%)';
|
||||
|
||||
/**
|
||||
* @param bool|int $raisePhpLimits If true, PHP settings will be raised if needed
|
||||
*/
|
||||
public function __construct($raisePhpLimits = true)
|
||||
{
|
||||
$this->raisePhpLimits = (bool) $raisePhpLimits;
|
||||
$this->memoryLimit = 128 * 1048576; // 128MB in bytes
|
||||
$this->pcreBacktrackLimit = 1000 * 1000;
|
||||
$this->pcreRecursionLimit = 500 * 1000;
|
||||
$this->hexToNamedColorsMap = Colors::getHexToNamedMap();
|
||||
$this->namedToHexColorsMap = Colors::getNamedToHexMap();
|
||||
$this->namedToHexColorsRegex = sprintf(
|
||||
'/([:,( ])(%s)( |,|\)|;|$)/Si',
|
||||
implode('|', array_keys($this->namedToHexColorsMap))
|
||||
);
|
||||
$this->numRegex = sprintf('-?\d*\.?\d+%s?', $this->unitsGroupRegex);
|
||||
$this->setShortenZeroValuesRegexes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses & minifies the given input CSS string
|
||||
* @param string $css
|
||||
* @return string
|
||||
*/
|
||||
public function run($css = '')
|
||||
{
|
||||
if (empty($css) || !is_string($css)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$this->resetRunProperties();
|
||||
|
||||
if ($this->raisePhpLimits) {
|
||||
$this->doRaisePhpLimits();
|
||||
}
|
||||
|
||||
return $this->minify($css);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to keep or remove sourcemap special comment.
|
||||
* Sourcemap comments are removed by default.
|
||||
* @param bool $keepSourceMapComment
|
||||
*/
|
||||
public function keepSourceMapComment($keepSourceMapComment = true)
|
||||
{
|
||||
$this->keepSourceMapComment = (bool) $keepSourceMapComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to keep or remove important comments.
|
||||
* Important comments outside of a declaration block are kept by default.
|
||||
* @param bool $removeImportantComments
|
||||
*/
|
||||
public function removeImportantComments($removeImportantComments = true)
|
||||
{
|
||||
$this->keepImportantComments = !(bool) $removeImportantComments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the approximate column after which long lines will be splitted in the output
|
||||
* with a linebreak.
|
||||
* @param int $position
|
||||
*/
|
||||
public function setLineBreakPosition($position)
|
||||
{
|
||||
$this->linebreakPosition = (int) $position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the memory limit for this script
|
||||
* @param int|string $limit
|
||||
*/
|
||||
public function setMemoryLimit($limit)
|
||||
{
|
||||
$this->memoryLimit = Utils::normalizeInt($limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum execution time for this script
|
||||
* @param int|string $seconds
|
||||
*/
|
||||
public function setMaxExecutionTime($seconds)
|
||||
{
|
||||
$this->maxExecutionTime = (int) $seconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the PCRE backtrack limit for this script
|
||||
* @param int $limit
|
||||
*/
|
||||
public function setPcreBacktrackLimit($limit)
|
||||
{
|
||||
$this->pcreBacktrackLimit = (int) $limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the PCRE recursion limit for this script
|
||||
* @param int $limit
|
||||
*/
|
||||
public function setPcreRecursionLimit($limit)
|
||||
{
|
||||
$this->pcreRecursionLimit = (int) $limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds regular expressions needed for shortening zero values
|
||||
*/
|
||||
private function setShortenZeroValuesRegexes()
|
||||
{
|
||||
$zeroRegex = '0'. $this->unitsGroupRegex;
|
||||
$numOrPosRegex = '('. $this->numRegex .'|top|left|bottom|right|center) ';
|
||||
$oneZeroSafeProperties = array(
|
||||
'(?:line-)?height',
|
||||
'(?:(?:min|max)-)?width',
|
||||
'top',
|
||||
'left',
|
||||
'background-position',
|
||||
'bottom',
|
||||
'right',
|
||||
'border(?:-(?:top|left|bottom|right))?(?:-width)?',
|
||||
'border-(?:(?:top|bottom)-(?:left|right)-)?radius',
|
||||
'column-(?:gap|width)',
|
||||
'margin(?:-(?:top|left|bottom|right))?',
|
||||
'outline-width',
|
||||
'padding(?:-(?:top|left|bottom|right))?'
|
||||
);
|
||||
|
||||
// First zero regex
|
||||
$regex = '/(^|;)('. implode('|', $oneZeroSafeProperties) .'):%s/Si';
|
||||
$this->shortenOneZeroesRegex = sprintf($regex, $zeroRegex);
|
||||
|
||||
// Multiple zeroes regexes
|
||||
$regex = '/(^|;)(margin|padding|border-(?:width|radius)|background-position):%s/Si';
|
||||
$this->shortenTwoZeroesRegex = sprintf($regex, $numOrPosRegex . $zeroRegex);
|
||||
$this->shortenThreeZeroesRegex = sprintf($regex, $numOrPosRegex . $numOrPosRegex . $zeroRegex);
|
||||
$this->shortenFourZeroesRegex = sprintf($regex, $numOrPosRegex . $numOrPosRegex . $numOrPosRegex . $zeroRegex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets properties whose value may change between runs
|
||||
*/
|
||||
private function resetRunProperties()
|
||||
{
|
||||
$this->comments = array();
|
||||
$this->ruleBodies = array();
|
||||
$this->preservedTokens = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to configure PHP to use at least the suggested minimum settings
|
||||
* @return void
|
||||
*/
|
||||
private function doRaisePhpLimits()
|
||||
{
|
||||
$phpLimits = array(
|
||||
'memory_limit' => $this->memoryLimit,
|
||||
'max_execution_time' => $this->maxExecutionTime,
|
||||
'pcre.backtrack_limit' => $this->pcreBacktrackLimit,
|
||||
'pcre.recursion_limit' => $this->pcreRecursionLimit
|
||||
);
|
||||
|
||||
// If current settings are higher respect them.
|
||||
foreach ($phpLimits as $name => $suggested) {
|
||||
$current = Utils::normalizeInt(ini_get($name));
|
||||
|
||||
if ($current >= $suggested) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// memoryLimit exception: allow -1 for "no memory limit".
|
||||
if ($name === 'memory_limit' && $current === -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// maxExecutionTime exception: allow 0 for "no memory limit".
|
||||
if ($name === 'max_execution_time' && $current === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ini_set($name, $suggested);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a preserved token
|
||||
* @param string $token
|
||||
* @return string The token ID string
|
||||
*/
|
||||
private function registerPreservedToken($token)
|
||||
{
|
||||
$tokenId = sprintf(self::PRESERVED_TOKEN, count($this->preservedTokens));
|
||||
$this->preservedTokens[$tokenId] = $token;
|
||||
return $tokenId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a candidate comment token
|
||||
* @param string $comment
|
||||
* @return string The comment token ID string
|
||||
*/
|
||||
private function registerCommentToken($comment)
|
||||
{
|
||||
$tokenId = sprintf(self::COMMENT_TOKEN, count($this->comments));
|
||||
$this->comments[$tokenId] = $comment;
|
||||
return $tokenId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a rule body token
|
||||
* @param string $body the minified rule body
|
||||
* @return string The rule body token ID string
|
||||
*/
|
||||
private function registerRuleBodyToken($body)
|
||||
{
|
||||
if (empty($body)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$tokenId = sprintf(self::RULE_BODY_TOKEN, count($this->ruleBodies));
|
||||
$this->ruleBodies[$tokenId] = $body;
|
||||
return $tokenId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses & minifies the given input CSS string
|
||||
* @param string $css
|
||||
* @return string
|
||||
*/
|
||||
private function minify($css)
|
||||
{
|
||||
// Process data urls
|
||||
$css = $this->processDataUrls($css);
|
||||
|
||||
// Process comments
|
||||
$css = preg_replace_callback(
|
||||
'/(?<!\\\\)\/\*(.*?)\*(?<!\\\\)\//Ss',
|
||||
array($this, 'processCommentsCallback'),
|
||||
$css
|
||||
);
|
||||
|
||||
// IE7: Process Microsoft matrix filters (whitespaces between Matrix parameters). Can contain strings inside.
|
||||
$css = preg_replace_callback(
|
||||
'/filter:\s*progid:DXImageTransform\.Microsoft\.Matrix\(([^)]+)\)/Ss',
|
||||
array($this, 'processOldIeSpecificMatrixDefinitionCallback'),
|
||||
$css
|
||||
);
|
||||
|
||||
// Process quoted unquotable attribute selectors to unquote them. Covers most common cases.
|
||||
// Likelyhood of a quoted attribute selector being a substring in a string: Very very low.
|
||||
$css = preg_replace(
|
||||
'/\[\s*([a-z][a-z-]+)\s*([\*\|\^\$~]?=)\s*[\'"](-?[a-z_][a-z0-9-_]+)[\'"]\s*\]/Ssi',
|
||||
'[$1$2$3]',
|
||||
$css
|
||||
);
|
||||
|
||||
// Process strings so their content doesn't get accidentally minified
|
||||
$css = preg_replace_callback(
|
||||
'/(?:"(?:[^\\\\"]|\\\\.|\\\\)*")|'."(?:'(?:[^\\\\']|\\\\.|\\\\)*')/S",
|
||||
array($this, 'processStringsCallback'),
|
||||
$css
|
||||
);
|
||||
|
||||
// Normalize all whitespace strings to single spaces. Easier to work with that way.
|
||||
$css = preg_replace('/\s+/S', ' ', $css);
|
||||
|
||||
// Process import At-rules with unquoted URLs so URI reserved characters such as a semicolon may be used safely.
|
||||
$css = preg_replace_callback(
|
||||
'/@import url\(([^\'"]+?)\)( |;)/Si',
|
||||
array($this, 'processImportUnquotedUrlAtRulesCallback'),
|
||||
$css
|
||||
);
|
||||
|
||||
// Process comments
|
||||
$css = $this->processComments($css);
|
||||
|
||||
// Process rule bodies
|
||||
$css = $this->processRuleBodies($css);
|
||||
|
||||
// Process at-rules and selectors
|
||||
$css = $this->processAtRulesAndSelectors($css);
|
||||
|
||||
// Restore preserved rule bodies before splitting
|
||||
$css = strtr($css, $this->ruleBodies);
|
||||
|
||||
// Split long lines in output if required
|
||||
$css = $this->processLongLineSplitting($css);
|
||||
|
||||
// Restore preserved comments and strings
|
||||
$css = strtr($css, $this->preservedTokens);
|
||||
|
||||
return trim($css);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches & replaces all data urls with tokens before we start compressing,
|
||||
* to avoid performance issues running some of the subsequent regexes against large string chunks.
|
||||
* @param string $css
|
||||
* @return string
|
||||
*/
|
||||
private function processDataUrls($css)
|
||||
{
|
||||
$ret = '';
|
||||
$searchOffset = $substrOffset = 0;
|
||||
|
||||
// Since we need to account for non-base64 data urls, we need to handle
|
||||
// ' and ) being part of the data string.
|
||||
while (preg_match('/url\(\s*(["\']?)data:/Si', $css, $m, PREG_OFFSET_CAPTURE, $searchOffset)) {
|
||||
$matchStartIndex = $m[0][1];
|
||||
$dataStartIndex = $matchStartIndex + 4; // url( length
|
||||
$searchOffset = $matchStartIndex + strlen($m[0][0]);
|
||||
$terminator = $m[1][0]; // ', " or empty (not quoted)
|
||||
$terminatorRegex = '/(?<!\\\\)'. (strlen($terminator) === 0 ? '' : $terminator.'\s*') .'(\))/S';
|
||||
|
||||
$ret .= substr($css, $substrOffset, $matchStartIndex - $substrOffset);
|
||||
|
||||
// Terminator found
|
||||
if (preg_match($terminatorRegex, $css, $matches, PREG_OFFSET_CAPTURE, $searchOffset)) {
|
||||
$matchEndIndex = $matches[1][1];
|
||||
$searchOffset = $matchEndIndex + 1;
|
||||
$token = substr($css, $dataStartIndex, $matchEndIndex - $dataStartIndex);
|
||||
|
||||
// Remove all spaces only for base64 encoded URLs.
|
||||
if (stripos($token, 'base64,') !== false) {
|
||||
$token = preg_replace('/\s+/S', '', $token);
|
||||
}
|
||||
|
||||
$ret .= 'url('. $this->registerPreservedToken(trim($token)) .')';
|
||||
// No end terminator found, re-add the whole match. Should we throw/warn here?
|
||||
} else {
|
||||
$ret .= substr($css, $matchStartIndex, $searchOffset - $matchStartIndex);
|
||||
}
|
||||
|
||||
$substrOffset = $searchOffset;
|
||||
}
|
||||
|
||||
$ret .= substr($css, $substrOffset);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all comments found as candidates to be preserved.
|
||||
* @param array $matches
|
||||
* @return string
|
||||
*/
|
||||
private function processCommentsCallback($matches)
|
||||
{
|
||||
return '/*'. $this->registerCommentToken($matches[1]) .'*/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Preserves old IE Matrix string definition
|
||||
* @param array $matches
|
||||
* @return string
|
||||
*/
|
||||
private function processOldIeSpecificMatrixDefinitionCallback($matches)
|
||||
{
|
||||
return 'filter:progid:DXImageTransform.Microsoft.Matrix('. $this->registerPreservedToken($matches[1]) .')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Preserves strings found
|
||||
* @param array $matches
|
||||
* @return string
|
||||
*/
|
||||
private function processStringsCallback($matches)
|
||||
{
|
||||
$match = $matches[0];
|
||||
$quote = substr($match, 0, 1);
|
||||
$match = substr($match, 1, -1);
|
||||
|
||||
// maybe the string contains a comment-like substring?
|
||||
// one, maybe more? put'em back then
|
||||
if (strpos($match, self::COMMENT_TOKEN_START) !== false) {
|
||||
$match = strtr($match, $this->comments);
|
||||
}
|
||||
|
||||
// minify alpha opacity in filter strings
|
||||
$match = str_ireplace('progid:DXImageTransform.Microsoft.Alpha(Opacity=', 'alpha(opacity=', $match);
|
||||
|
||||
return $quote . $this->registerPreservedToken($match) . $quote;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches & replaces all import at-rule unquoted urls with tokens so URI reserved characters such as a semicolon
|
||||
* may be used safely in a URL.
|
||||
* @param array $matches
|
||||
* @return string
|
||||
*/
|
||||
private function processImportUnquotedUrlAtRulesCallback($matches)
|
||||
{
|
||||
return '@import url('. $this->registerPreservedToken($matches[1]) .')'. $matches[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Preserves or removes comments found.
|
||||
* @param string $css
|
||||
* @return string
|
||||
*/
|
||||
private function processComments($css)
|
||||
{
|
||||
foreach ($this->comments as $commentId => $comment) {
|
||||
$commentIdString = '/*'. $commentId .'*/';
|
||||
|
||||
// ! in the first position of the comment means preserve
|
||||
// so push to the preserved tokens keeping the !
|
||||
if ($this->keepImportantComments && strpos($comment, '!') === 0) {
|
||||
$preservedTokenId = $this->registerPreservedToken($comment);
|
||||
// Put new lines before and after /*! important comments
|
||||
$css = str_replace($commentIdString, "\n/*$preservedTokenId*/\n", $css);
|
||||
continue;
|
||||
}
|
||||
|
||||
// # sourceMappingURL= in the first position of the comment means sourcemap
|
||||
// so push to the preserved tokens if {$this->keepSourceMapComment} is truthy.
|
||||
if ($this->keepSourceMapComment && strpos($comment, '# sourceMappingURL=') === 0) {
|
||||
$preservedTokenId = $this->registerPreservedToken($comment);
|
||||
// Add new line before the sourcemap comment
|
||||
$css = str_replace($commentIdString, "\n/*$preservedTokenId*/", $css);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Keep empty comments after child selectors (IE7 hack)
|
||||
// e.g. html >/**/ body
|
||||
if (strlen($comment) === 0 && strpos($css, '>/*'.$commentId) !== false) {
|
||||
$css = str_replace($commentId, $this->registerPreservedToken(''), $css);
|
||||
continue;
|
||||
}
|
||||
|
||||
// in all other cases kill the comment
|
||||
$css = str_replace($commentIdString, '', $css);
|
||||
}
|
||||
|
||||
// Normalize whitespace again
|
||||
$css = preg_replace('/ +/S', ' ', $css);
|
||||
|
||||
return $css;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds, minifies & preserves all rule bodies.
|
||||
* @param string $css the whole stylesheet.
|
||||
* @return string
|
||||
*/
|
||||
private function processRuleBodies($css)
|
||||
{
|
||||
$ret = '';
|
||||
$searchOffset = $substrOffset = 0;
|
||||
|
||||
while (($blockStartPos = strpos($css, '{', $searchOffset)) !== false) {
|
||||
$blockEndPos = strpos($css, '}', $blockStartPos);
|
||||
$nextBlockStartPos = strpos($css, '{', $blockStartPos + 1);
|
||||
$ret .= substr($css, $substrOffset, $blockStartPos - $substrOffset);
|
||||
|
||||
if ($nextBlockStartPos !== false && $nextBlockStartPos < $blockEndPos) {
|
||||
$ret .= substr($css, $blockStartPos, $nextBlockStartPos - $blockStartPos);
|
||||
$searchOffset = $nextBlockStartPos;
|
||||
} else {
|
||||
$ruleBody = substr($css, $blockStartPos + 1, $blockEndPos - $blockStartPos - 1);
|
||||
$ruleBodyToken = $this->registerRuleBodyToken($this->processRuleBody($ruleBody));
|
||||
$ret .= '{'. $ruleBodyToken .'}';
|
||||
$searchOffset = $blockEndPos + 1;
|
||||
}
|
||||
|
||||
$substrOffset = $searchOffset;
|
||||
}
|
||||
|
||||
$ret .= substr($css, $substrOffset);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compresses non-group rule bodies.
|
||||
* @param string $body The rule body without curly braces
|
||||
* @return string
|
||||
*/
|
||||
private function processRuleBody($body)
|
||||
{
|
||||
$body = trim($body);
|
||||
|
||||
// Remove spaces before the things that should not have spaces before them.
|
||||
$body = preg_replace('/ ([:=,)*\/;\n])/S', '$1', $body);
|
||||
|
||||
// Remove the spaces after the things that should not have spaces after them.
|
||||
$body = preg_replace('/([:=,(*\/!;\n]) /S', '$1', $body);
|
||||
|
||||
// Replace multiple semi-colons in a row by a single one
|
||||
$body = preg_replace('/;;+/S', ';', $body);
|
||||
|
||||
// Remove semicolon before closing brace except when:
|
||||
// - The last property is prefixed with a `*` (lte IE7 hack) to avoid issues on Symbian S60 3.x browsers.
|
||||
if (!preg_match('/\*[a-z0-9-]+:[^;]+;$/Si', $body)) {
|
||||
$body = rtrim($body, ';');
|
||||
}
|
||||
|
||||
// Remove important comments inside a rule body (because they make no sense here).
|
||||
if (strpos($body, '/*') !== false) {
|
||||
$body = preg_replace('/\n?\/\*[A-Z0-9_]+\*\/\n?/S', '', $body);
|
||||
}
|
||||
|
||||
// Empty rule body? Exit :)
|
||||
if (empty($body)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Shorten font-weight values
|
||||
$body = preg_replace(
|
||||
array('/(font-weight:)bold\b/Si', '/(font-weight:)normal\b/Si'),
|
||||
array('${1}700', '${1}400'),
|
||||
$body
|
||||
);
|
||||
|
||||
// Shorten background property
|
||||
$body = preg_replace('/(background:)(?:none|transparent)( !|;|$)/Si', '${1}0 0$2', $body);
|
||||
|
||||
// Shorten opacity IE filter
|
||||
$body = str_ireplace('progid:DXImageTransform.Microsoft.Alpha(Opacity=', 'alpha(opacity=', $body);
|
||||
|
||||
// Shorten colors from rgb(51,102,153) to #336699, rgb(100%,0%,0%) to #ff0000 (sRGB color space)
|
||||
// Shorten colors from hsl(0, 100%, 50%) to #ff0000 (sRGB color space)
|
||||
// This makes it more likely that it'll get further compressed in the next step.
|
||||
$body = preg_replace_callback(
|
||||
'/(rgb|hsl)\(([0-9,.% -]+)\)(.|$)/Si',
|
||||
array($this, 'shortenHslAndRgbToHexCallback'),
|
||||
$body
|
||||
);
|
||||
|
||||
// Shorten colors from #AABBCC to #ABC or shorter color name:
|
||||
// - Look for hex colors which don't have a "=" in front of them (to avoid MSIE filters)
|
||||
$body = preg_replace_callback(
|
||||
'/(?<!=)#([0-9a-f]{3,6})( |,|\)|;|$)/Si',
|
||||
array($this, 'shortenHexColorsCallback'),
|
||||
$body
|
||||
);
|
||||
|
||||
// Shorten long named colors with a shorter HEX counterpart: white -> #fff.
|
||||
// Run at least 2 times to cover most cases
|
||||
$body = preg_replace_callback(
|
||||
array($this->namedToHexColorsRegex, $this->namedToHexColorsRegex),
|
||||
array($this, 'shortenNamedColorsCallback'),
|
||||
$body
|
||||
);
|
||||
|
||||
// Replace positive sign from numbers before the leading space is removed.
|
||||
// +1.2em to 1.2em, +.8px to .8px, +2% to 2%
|
||||
$body = preg_replace('/([ :,(])\+(\.?\d+)/S', '$1$2', $body);
|
||||
|
||||
// shorten ms to s
|
||||
$body = preg_replace_callback('/([ :,(])(-?)(\d{3,})ms/Si', function ($matches) {
|
||||
return $matches[1] . $matches[2] . ((int) $matches[3] / 1000) .'s';
|
||||
}, $body);
|
||||
|
||||
// Remove leading zeros from integer and float numbers.
|
||||
// 000.6 to .6, -0.8 to -.8, 0050 to 50, -01.05 to -1.05
|
||||
$body = preg_replace('/([ :,(])(-?)0+([1-9]?\.?\d+)/S', '$1$2$3', $body);
|
||||
|
||||
// Remove trailing zeros from float numbers.
|
||||
// -6.0100em to -6.01em, .0100 to .01, 1.200px to 1.2px
|
||||
$body = preg_replace('/([ :,(])(-?\d?\.\d+?)0+([^\d])/S', '$1$2$3', $body);
|
||||
|
||||
// Remove trailing .0 -> -9.0 to -9
|
||||
$body = preg_replace('/([ :,(])(-?\d+)\.0([^\d])/S', '$1$2$3', $body);
|
||||
|
||||
// Replace 0 length numbers with 0
|
||||
$body = preg_replace('/([ :,(])-?\.?0+([^\d])/S', '${1}0$2', $body);
|
||||
|
||||
// Shorten zero values for safe properties only
|
||||
$body = preg_replace(
|
||||
array(
|
||||
$this->shortenOneZeroesRegex,
|
||||
$this->shortenTwoZeroesRegex,
|
||||
$this->shortenThreeZeroesRegex,
|
||||
$this->shortenFourZeroesRegex
|
||||
),
|
||||
array(
|
||||
'$1$2:0',
|
||||
'$1$2:$3 0',
|
||||
'$1$2:$3 $4 0',
|
||||
'$1$2:$3 $4 $5 0'
|
||||
),
|
||||
$body
|
||||
);
|
||||
|
||||
// Replace 0 0 0; or 0 0 0 0; with 0 0 for background-position property.
|
||||
$body = preg_replace('/(background-position):0(?: 0){2,3}( !|;|$)/Si', '$1:0 0$2', $body);
|
||||
|
||||
// Shorten suitable shorthand properties with repeated values
|
||||
$body = preg_replace(
|
||||
array(
|
||||
'/(margin|padding|border-(?:width|radius)):('.$this->numRegex.')(?: \2)+( !|;|$)/Si',
|
||||
'/(border-(?:style|color)):([#a-z0-9]+)(?: \2)+( !|;|$)/Si'
|
||||
),
|
||||
'$1:$2$3',
|
||||
$body
|
||||
);
|
||||
$body = preg_replace(
|
||||
array(
|
||||
'/(margin|padding|border-(?:width|radius)):'.
|
||||
'('.$this->numRegex.') ('.$this->numRegex.') \2 \3( !|;|$)/Si',
|
||||
'/(border-(?:style|color)):([#a-z0-9]+) ([#a-z0-9]+) \2 \3( !|;|$)/Si'
|
||||
),
|
||||
'$1:$2 $3$4',
|
||||
$body
|
||||
);
|
||||
$body = preg_replace(
|
||||
array(
|
||||
'/(margin|padding|border-(?:width|radius)):'.
|
||||
'('.$this->numRegex.') ('.$this->numRegex.') ('.$this->numRegex.') \3( !|;|$)/Si',
|
||||
'/(border-(?:style|color)):([#a-z0-9]+) ([#a-z0-9]+) ([#a-z0-9]+) \3( !|;|$)/Si'
|
||||
),
|
||||
'$1:$2 $3 $4$5',
|
||||
$body
|
||||
);
|
||||
|
||||
// Lowercase some common functions that can be values
|
||||
$body = preg_replace_callback(
|
||||
'/(?:attr|blur|brightness|circle|contrast|cubic-bezier|drop-shadow|ellipse|from|grayscale|'.
|
||||
'hsla?|hue-rotate|inset|invert|local|minmax|opacity|perspective|polygon|rgba?|rect|repeat|saturate|sepia|'.
|
||||
'steps|to|url|var|-webkit-gradient|'.
|
||||
'(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?(?:calc|(?:repeating-)?(?:linear|radial)-gradient))\(/Si',
|
||||
array($this, 'strtolowerCallback'),
|
||||
$body
|
||||
);
|
||||
|
||||
// Lowercase all uppercase properties
|
||||
$body = preg_replace_callback('/(?:^|;)[A-Z-]+:/S', array($this, 'strtolowerCallback'), $body);
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compresses At-rules and selectors.
|
||||
* @param string $css the whole stylesheet with rule bodies tokenized.
|
||||
* @return string
|
||||
*/
|
||||
private function processAtRulesAndSelectors($css)
|
||||
{
|
||||
$charset = '';
|
||||
$imports = '';
|
||||
$namespaces = '';
|
||||
|
||||
// Remove spaces before the things that should not have spaces before them.
|
||||
$css = preg_replace('/ ([@{};>+)\]~=,\/\n])/S', '$1', $css);
|
||||
|
||||
// Remove the spaces after the things that should not have spaces after them.
|
||||
$css = preg_replace('/([{}:;>+(\[~=,\/\n]) /S', '$1', $css);
|
||||
|
||||
// Shorten shortable double colon (CSS3) pseudo-elements to single colon (CSS2)
|
||||
$css = preg_replace('/::(before|after|first-(?:line|letter))(\{|,)/Si', ':$1$2', $css);
|
||||
|
||||
// Retain space for special IE6 cases
|
||||
$css = preg_replace_callback('/:first-(line|letter)(\{|,)/Si', function ($matches) {
|
||||
return ':first-'. strtolower($matches[1]) .' '. $matches[2];
|
||||
}, $css);
|
||||
|
||||
// Find a fraction that may used in some @media queries such as: (min-aspect-ratio: 1/1)
|
||||
// Add token to add the "/" back in later
|
||||
$css = preg_replace('/\(([a-z-]+):([0-9]+)\/([0-9]+)\)/Si', '($1:$2'. self::QUERY_FRACTION .'$3)', $css);
|
||||
|
||||
// Remove empty rule blocks up to 2 levels deep.
|
||||
$css = preg_replace(array_fill(0, 2, '/(\{)[^{};\/\n]+\{\}/S'), '$1', $css);
|
||||
$css = preg_replace('/[^{};\/\n]+\{\}/S', '', $css);
|
||||
|
||||
// Two important comments next to each other? Remove extra newline.
|
||||
if ($this->keepImportantComments) {
|
||||
$css = str_replace("\n\n", "\n", $css);
|
||||
}
|
||||
|
||||
// Restore fraction
|
||||
$css = str_replace(self::QUERY_FRACTION, '/', $css);
|
||||
|
||||
// Lowercase some popular @directives
|
||||
$css = preg_replace_callback(
|
||||
'/(?<!\\\\)@(?:charset|document|font-face|import|(?:-(?:atsc|khtml|moz|ms|o|wap|webkit)-)?keyframes|media|'.
|
||||
'namespace|page|supports|viewport)/Si',
|
||||
array($this, 'strtolowerCallback'),
|
||||
$css
|
||||
);
|
||||
|
||||
// Lowercase some popular media types
|
||||
$css = preg_replace_callback(
|
||||
'/[ ,](?:all|aural|braille|handheld|print|projection|screen|tty|tv|embossed|speech)[ ,;{]/Si',
|
||||
array($this, 'strtolowerCallback'),
|
||||
$css
|
||||
);
|
||||
|
||||
// Lowercase some common pseudo-classes & pseudo-elements
|
||||
$css = preg_replace_callback(
|
||||
'/(?<!\\\\):(?:active|after|before|checked|default|disabled|empty|enabled|first-(?:child|of-type)|'.
|
||||
'focus(?:-within)?|hover|indeterminate|in-range|invalid|lang\(|last-(?:child|of-type)|left|link|not\(|'.
|
||||
'nth-(?:child|of-type)\(|nth-last-(?:child|of-type)\(|only-(?:child|of-type)|optional|out-of-range|'.
|
||||
'read-(?:only|write)|required|right|root|:selection|target|valid|visited)/Si',
|
||||
array($this, 'strtolowerCallback'),
|
||||
$css
|
||||
);
|
||||
|
||||
// @charset handling
|
||||
if (preg_match($this->charsetRegex, $css, $matches)) {
|
||||
// Keep the first @charset at-rule found
|
||||
$charset = $matches[0];
|
||||
// Delete all @charset at-rules
|
||||
$css = preg_replace($this->charsetRegex, '', $css);
|
||||
}
|
||||
|
||||
// @import handling
|
||||
$css = preg_replace_callback($this->importRegex, function ($matches) use (&$imports) {
|
||||
// Keep all @import at-rules found for later
|
||||
$imports .= $matches[0];
|
||||
// Delete all @import at-rules
|
||||
return '';
|
||||
}, $css);
|
||||
|
||||
// @namespace handling
|
||||
$css = preg_replace_callback($this->namespaceRegex, function ($matches) use (&$namespaces) {
|
||||
// Keep all @namespace at-rules found for later
|
||||
$namespaces .= $matches[0];
|
||||
// Delete all @namespace at-rules
|
||||
return '';
|
||||
}, $css);
|
||||
|
||||
// Order critical at-rules:
|
||||
// 1. @charset first
|
||||
// 2. @imports below @charset
|
||||
// 3. @namespaces below @imports
|
||||
$css = $charset . $imports . $namespaces . $css;
|
||||
|
||||
return $css;
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits long lines after a specific column.
|
||||
*
|
||||
* Some source control tools don't like it when files containing lines longer
|
||||
* than, say 8000 characters, are checked in. The linebreak option is used in
|
||||
* that case to split long lines after a specific column.
|
||||
*
|
||||
* @param string $css the whole stylesheet.
|
||||
* @return string
|
||||
*/
|
||||
private function processLongLineSplitting($css)
|
||||
{
|
||||
if ($this->linebreakPosition > 0) {
|
||||
$l = strlen($css);
|
||||
$offset = $this->linebreakPosition;
|
||||
while (preg_match('/(?<!\\\\)\}(?!\n)/S', $css, $matches, PREG_OFFSET_CAPTURE, $offset)) {
|
||||
$matchIndex = $matches[0][1];
|
||||
$css = substr_replace($css, "\n", $matchIndex + 1, 0);
|
||||
$offset = $matchIndex + 2 + $this->linebreakPosition;
|
||||
$l += 1;
|
||||
if ($offset > $l) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $css;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts hsl() & rgb() colors to HEX format.
|
||||
* @param $matches
|
||||
* @return string
|
||||
*/
|
||||
private function shortenHslAndRgbToHexCallback($matches)
|
||||
{
|
||||
$type = $matches[1];
|
||||
$values = explode(',', $matches[2]);
|
||||
$terminator = $matches[3];
|
||||
|
||||
if ($type === 'hsl') {
|
||||
$values = Utils::hslToRgb($values);
|
||||
}
|
||||
|
||||
$hexColors = Utils::rgbToHex($values);
|
||||
|
||||
// Restore space after rgb() or hsl() function in some cases such as:
|
||||
// background-image: linear-gradient(to bottom, rgb(210,180,140) 10%, rgb(255,0,0) 90%);
|
||||
if (!empty($terminator) && !preg_match('/[ ,);]/S', $terminator)) {
|
||||
$terminator = ' '. $terminator;
|
||||
}
|
||||
|
||||
return '#'. implode('', $hexColors) . $terminator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compresses HEX color values of the form #AABBCC to #ABC or short color name.
|
||||
* @param $matches
|
||||
* @return string
|
||||
*/
|
||||
private function shortenHexColorsCallback($matches)
|
||||
{
|
||||
$hex = $matches[1];
|
||||
|
||||
// Shorten suitable 6 chars HEX colors
|
||||
if (strlen($hex) === 6 && preg_match('/^([0-9a-f])\1([0-9a-f])\2([0-9a-f])\3$/Si', $hex, $m)) {
|
||||
$hex = $m[1] . $m[2] . $m[3];
|
||||
}
|
||||
|
||||
// Lowercase
|
||||
$hex = '#'. strtolower($hex);
|
||||
|
||||
// Replace Hex colors with shorter color names
|
||||
$color = array_key_exists($hex, $this->hexToNamedColorsMap) ? $this->hexToNamedColorsMap[$hex] : $hex;
|
||||
|
||||
return $color . $matches[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* Shortens all named colors with a shorter HEX counterpart for a set of safe properties
|
||||
* e.g. white -> #fff
|
||||
* @param array $matches
|
||||
* @return string
|
||||
*/
|
||||
private function shortenNamedColorsCallback($matches)
|
||||
{
|
||||
return $matches[1] . $this->namedToHexColorsMap[strtolower($matches[2])] . $matches[3];
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a string lowercase
|
||||
* @param array $matches
|
||||
* @return string
|
||||
*/
|
||||
private function strtolowerCallback($matches)
|
||||
{
|
||||
return strtolower($matches[0]);
|
||||
}
|
||||
}
|
||||
149
components/com_jce/editor/libraries/classes/vendor/cssmin/src/Utils.php
vendored
Normal file
149
components/com_jce/editor/libraries/classes/vendor/cssmin/src/Utils.php
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
namespace tubalmartin\CssMin;
|
||||
|
||||
class Utils
|
||||
{
|
||||
/**
|
||||
* Clamps a number between a minimum and a maximum value.
|
||||
* @param int|float $n the number to clamp
|
||||
* @param int|float $min the lower end number allowed
|
||||
* @param int|float $max the higher end number allowed
|
||||
* @return int|float
|
||||
*/
|
||||
public static function clampNumber($n, $min, $max)
|
||||
{
|
||||
return min(max($n, $min), $max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clamps a RGB color number outside the sRGB color space
|
||||
* @param int|float $n the number to clamp
|
||||
* @return int|float
|
||||
*/
|
||||
public static function clampNumberSrgb($n)
|
||||
{
|
||||
return self::clampNumber($n, 0, 255);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a HSL color into a RGB color
|
||||
* @param array $hslValues
|
||||
* @return array
|
||||
*/
|
||||
public static function hslToRgb($hslValues)
|
||||
{
|
||||
$h = floatval($hslValues[0]);
|
||||
$s = floatval(str_replace('%', '', $hslValues[1]));
|
||||
$l = floatval(str_replace('%', '', $hslValues[2]));
|
||||
|
||||
// Wrap and clamp, then fraction!
|
||||
$h = ((($h % 360) + 360) % 360) / 360;
|
||||
$s = self::clampNumber($s, 0, 100) / 100;
|
||||
$l = self::clampNumber($l, 0, 100) / 100;
|
||||
|
||||
if ($s == 0) {
|
||||
$r = $g = $b = self::roundNumber(255 * $l);
|
||||
} else {
|
||||
$v2 = $l < 0.5 ? $l * (1 + $s) : ($l + $s) - ($s * $l);
|
||||
$v1 = (2 * $l) - $v2;
|
||||
$r = self::roundNumber(255 * self::hueToRgb($v1, $v2, $h + (1/3)));
|
||||
$g = self::roundNumber(255 * self::hueToRgb($v1, $v2, $h));
|
||||
$b = self::roundNumber(255 * self::hueToRgb($v1, $v2, $h - (1/3)));
|
||||
}
|
||||
|
||||
return array($r, $g, $b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests and selects the correct formula for each RGB color channel
|
||||
* @param $v1
|
||||
* @param $v2
|
||||
* @param $vh
|
||||
* @return mixed
|
||||
*/
|
||||
public static function hueToRgb($v1, $v2, $vh)
|
||||
{
|
||||
$vh = $vh < 0 ? $vh + 1 : ($vh > 1 ? $vh - 1 : $vh);
|
||||
|
||||
if ($vh * 6 < 1) {
|
||||
return $v1 + ($v2 - $v1) * 6 * $vh;
|
||||
}
|
||||
|
||||
if ($vh * 2 < 1) {
|
||||
return $v2;
|
||||
}
|
||||
|
||||
if ($vh * 3 < 2) {
|
||||
return $v1 + ($v2 - $v1) * ((2 / 3) - $vh) * 6;
|
||||
}
|
||||
|
||||
return $v1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert strings like "64M" or "30" to int values
|
||||
* @param mixed $size
|
||||
* @return int
|
||||
*/
|
||||
public static function normalizeInt($size)
|
||||
{
|
||||
if (is_string($size)) {
|
||||
$letter = substr($size, -1);
|
||||
$size = intval($size);
|
||||
switch ($letter) {
|
||||
case 'M':
|
||||
case 'm':
|
||||
return (int) $size * 1048576;
|
||||
case 'K':
|
||||
case 'k':
|
||||
return (int) $size * 1024;
|
||||
case 'G':
|
||||
case 'g':
|
||||
return (int) $size * 1073741824;
|
||||
}
|
||||
}
|
||||
return (int) $size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a string containing and RGB percentage value into a RGB integer value i.e. '90%' -> 229.5
|
||||
* @param $rgbPercentage
|
||||
* @return int
|
||||
*/
|
||||
public static function rgbPercentageToRgbInteger($rgbPercentage)
|
||||
{
|
||||
if (strpos($rgbPercentage, '%') !== false) {
|
||||
$rgbPercentage = self::roundNumber(floatval(str_replace('%', '', $rgbPercentage)) * 2.55);
|
||||
}
|
||||
|
||||
return intval($rgbPercentage, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a RGB color into a HEX color
|
||||
* @param array $rgbColors
|
||||
* @return array
|
||||
*/
|
||||
public static function rgbToHex($rgbColors)
|
||||
{
|
||||
$hexColors = array();
|
||||
|
||||
// Values outside the sRGB color space should be clipped (0-255)
|
||||
for ($i = 0, $l = count($rgbColors); $i < $l; $i++) {
|
||||
$hexColors[$i] = sprintf("%02x", self::clampNumberSrgb(self::rgbPercentageToRgbInteger($rgbColors[$i])));
|
||||
}
|
||||
|
||||
return $hexColors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds a number to its closest integer
|
||||
* @param $n
|
||||
* @return int
|
||||
*/
|
||||
public static function roundNumber($n)
|
||||
{
|
||||
return intval(round(floatval($n)), 10);
|
||||
}
|
||||
}
|
||||
1
components/com_jce/editor/libraries/classes/vendor/cssmin/src/index.html
vendored
Normal file
1
components/com_jce/editor/libraries/classes/vendor/cssmin/src/index.html
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
||||
1
components/com_jce/editor/libraries/classes/vendor/index.html
vendored
Normal file
1
components/com_jce/editor/libraries/classes/vendor/index.html
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
||||
150
components/com_jce/editor/libraries/classes/view.php
Normal file
150
components/com_jce/editor/libraries/classes/view.php
Normal file
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 2 or later - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
* JCE is free software. This version may have been modified pursuant
|
||||
* to the GNU General Public License, and as distributed it includes or
|
||||
* is derivative of works licensed under the GNU General Public License or
|
||||
* other free or open source software licenses
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
final class WFView extends JObject
|
||||
{
|
||||
private $path = array();
|
||||
|
||||
public function __construct($config = array())
|
||||
{
|
||||
if (!array_key_exists('base_path', $config)) {
|
||||
$config['base_path'] = WF_EDITOR_LIBRARIES;
|
||||
}
|
||||
|
||||
if (!array_key_exists('layout', $config)) {
|
||||
$config['layout'] = 'default';
|
||||
}
|
||||
|
||||
if (!array_key_exists('name', $config)) {
|
||||
$config['name'] = '';
|
||||
}
|
||||
|
||||
$this->setProperties($config);
|
||||
|
||||
if (array_key_exists('template_path', $config)) {
|
||||
$this->addTemplatePath($config['template_path']);
|
||||
} else {
|
||||
$this->addTemplatePath($this->get('base_path') . '/views/' . $this->getName() . '/tmpl');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute and display a template script.
|
||||
*
|
||||
* @param string $tpl The name of the template file to parse;
|
||||
* automatically searches through the template paths
|
||||
*
|
||||
* @throws object An JError object.
|
||||
* JView::display()
|
||||
*
|
||||
* @copyright Copyright Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved
|
||||
* @license GNU/GPL, see LICENSE.php
|
||||
*/
|
||||
public function display($tpl = null)
|
||||
{
|
||||
$result = $this->loadTemplate($tpl);
|
||||
|
||||
if ($result instanceof Exception) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
echo $result;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return $this->get('name');
|
||||
}
|
||||
|
||||
public function setLayout($layout)
|
||||
{
|
||||
$this->set('layout', $layout);
|
||||
}
|
||||
|
||||
public function getLayout()
|
||||
{
|
||||
return $this->get('layout');
|
||||
}
|
||||
|
||||
public function addTemplatePath($path)
|
||||
{
|
||||
$this->path[] = $path;
|
||||
}
|
||||
|
||||
public function getTemplatePath()
|
||||
{
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a template file.
|
||||
*
|
||||
* @param string $tpl The name of the template source file ...
|
||||
* automatically searches the template paths and compiles as needed
|
||||
*
|
||||
* @return string The output of the the template script.
|
||||
*
|
||||
* JView::loadTemplate()
|
||||
*
|
||||
* @copyright Copyright Copyright (C) 2005 - 2010 Open Source Matters. All rights reserved
|
||||
* @license GNU/GPL, see LICENSE.php
|
||||
*/
|
||||
public function loadTemplate($tpl = null)
|
||||
{
|
||||
// clear prior output
|
||||
$output = null;
|
||||
$template = null;
|
||||
|
||||
//create the template file name based on the layout
|
||||
$file = isset($tpl) ? $this->getLayout() . '_' . $tpl : $this->getLayout();
|
||||
|
||||
// clean the file name
|
||||
$file = preg_replace('/[^A-Z0-9_\.-]/i', '', $file);
|
||||
|
||||
if (isset($tpl)) {
|
||||
$tpl = preg_replace('/[^A-Z0-9_\.-]/i', '', $tpl);
|
||||
}
|
||||
|
||||
// load the template script
|
||||
jimport('joomla.filesystem.path');
|
||||
|
||||
$path = $this->getTemplatePath();
|
||||
|
||||
$template = JPath::find($path, $file . '.php');
|
||||
|
||||
if ($template != false) {
|
||||
// unset so as not to introduce into template scope
|
||||
unset($tpl);
|
||||
unset($file);
|
||||
|
||||
// never allow a 'this' property
|
||||
if (isset($this->this)) {
|
||||
unset($this->this);
|
||||
}
|
||||
|
||||
// start capturing output into a buffer
|
||||
ob_start();
|
||||
// include the requested template filename in the local scope
|
||||
// (this will execute the view logic).
|
||||
include $template;
|
||||
|
||||
// done with the requested template; get the buffer and
|
||||
// clear it.
|
||||
$output = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
return $output;
|
||||
} else {
|
||||
throw new InvalidArgumentException('Layout "' . $file . '" not found in Paths ' . implode(', ', $path));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user