first commit
This commit is contained in:
12
administrator/components/com_jce/access.xml
Normal file
12
administrator/components/com_jce/access.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<access component="com_jce">
|
||||
<section name="component">
|
||||
<action name="core.admin" title="JACTION_ADMIN" description="JACTION_ADMIN_COMPONENT_DESC" />
|
||||
<action name="core.manage" title="JACTION_MANAGE" description="JACTION_MANAGE_COMPONENT_DESC" />
|
||||
<action name="jce.config" title="WF_ACTION_CONFIG" description="WF_ACTION_CONFIG_DESC" />
|
||||
<action name="jce.profiles" title="WF_ACTION_PROFILES" description="WF_ACTION_PROFILES_DESC" />
|
||||
<action name="jce.preferences" title="WF_ACTION_PREFERENCES" description="WF_ACTION_PREFERENCES_DESC" />
|
||||
<action name="jce.browser" title="WF_ACTION_BROWSER" description="WF_ACTION_BROWSER_DESC" />
|
||||
<action name="jce.mediabox" title="WF_ACTION_MEDIABOX" description="WF_ACTION_MEDIABOX_DESC" />
|
||||
</section>
|
||||
</access>
|
||||
50
administrator/components/com_jce/config.xml
Normal file
50
administrator/components/com_jce/config.xml
Normal file
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<config>
|
||||
<fieldset name="permissions" label="JCONFIG_PERMISSIONS_LABEL" description="JCONFIG_PERMISSIONS_DESC">
|
||||
<field name="rules" type="rules" label="JCONFIG_PERMISSIONS_LABEL" class="inputbox" filter="rules" component="com_jce" section="component" />
|
||||
</fieldset>
|
||||
|
||||
<fieldset name="standard" label="WF_PREFERENCES_STANDARD">
|
||||
|
||||
<field name="custom_help" type="radio" default="0" label="WF_HELP_CUSTOM" class="btn-group btn-group-yesno" description="WF_HELP_CUSTOM_DESC">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
|
||||
<field name="help_url" type="text" size="50" default="" label="WF_HELP_URL" description="WF_HELP_URL_DESC" showon="custom_help:1" />
|
||||
|
||||
<field name="help_method" type="list" default="reference" label="WF_HELP_URL_METHOD" description="WF_HELP_URL_METHOD_DESC" showon="custom_help:1">
|
||||
<option value="reference">WF_HELP_URL_KEYREFERENCE</option>
|
||||
<option value="sef">WF_HELP_URL_SEF</option>
|
||||
</field>
|
||||
|
||||
<field name="help_pattern" type="text" size="50" default="" hint="/$1/$2/$3" label="WF_HELP_PATTERN" description="WF_HELP_PATTERN_DESC" showon="help_method:sef" />
|
||||
|
||||
<field name="feed" type="radio" default="0" label="WF_CPANEL_FEED" description="WF_CPANEL_FEED_DESC" class="btn-group btn-group-yesno">
|
||||
<option value="1">WF_OPTION_YES</option>
|
||||
<option value="0">WF_OPTION_NO</option>
|
||||
</field>
|
||||
|
||||
<field name="feed_limit" type="list" default="2" label="WF_CPANEL_FEED_LIMIT" description="WF_CPANEL_FEED_LIMIT_DESC">
|
||||
<option value="1">1</option>
|
||||
<option value="2">2</option>
|
||||
<option value="3">3</option>
|
||||
<option value="4">4</option>
|
||||
<option value="5">5</option>
|
||||
</field>
|
||||
|
||||
<field name="inline_help" type="radio" default="1" label="WF_ADMIN_INLINE_HELP" description="WF_ADMIN_INLINE_HELP_DESC" class="btn-group btn-group-yesno">
|
||||
<option value="1">WF_OPTION_YES</option>
|
||||
<option value="0">WF_OPTION_NO</option>
|
||||
</field>
|
||||
|
||||
<field name="replace_media_manager" type="radio" default="1" label="WF_CPANEL_REPLACE_MEDIAMANAGER_LABEL" class="btn-group btn-group-yesno" description="WF_CPANEL_REPLACE_MEDIAMANAGER_DESCRIPTION">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
|
||||
</fieldset>
|
||||
<fieldset name="updates" label="WF_PREFERENCES_UPDATES">
|
||||
<field name="updates_key" type="password" size="50" default="" label="WF_UPDATES_KEY" description="WF_UPDATES_KEY_DESC" />
|
||||
</fieldset>
|
||||
</config>
|
||||
135
administrator/components/com_jce/controller.php
Normal file
135
administrator/components/com_jce/controller.php
Normal file
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 3 - 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
|
||||
*/
|
||||
// no direct access
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
JLoader::import('joomla.application.component.controller');
|
||||
|
||||
/**
|
||||
* JCE Component Controller.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
class JceController extends JControllerLegacy
|
||||
{
|
||||
/**
|
||||
* @var string The extension for which the categories apply
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected $extension;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings
|
||||
*
|
||||
* @see JController
|
||||
* @since 1.5
|
||||
*/
|
||||
public function __construct($config = array())
|
||||
{
|
||||
parent::__construct($config);
|
||||
|
||||
// Guess the JText message prefix. Defaults to the option.
|
||||
if (empty($this->extension)) {
|
||||
$this->extension = $this->input->get('extension', 'com_jce');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to display a view.
|
||||
*
|
||||
* @param bool $cachable If true, the view output will be cached
|
||||
* @param array $urlparams An array of safe url parameters and their variable types, for valid values see {@link JFilterInput::clean()}
|
||||
*
|
||||
* @return JController This object to support chaining
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public function display($cachable = false, $urlparams = false)
|
||||
{
|
||||
// Get the document object.
|
||||
$document = JFactory::getDocument();
|
||||
$app = JFactory::getApplication();
|
||||
$user = JFactory::getUser();
|
||||
|
||||
JFactory::getLanguage()->load('com_jce', JPATH_ADMINISTRATOR);
|
||||
|
||||
// Set the default view name and format from the Request.
|
||||
$vName = $app->input->get('view', 'cpanel');
|
||||
$vFormat = $document->getType();
|
||||
$lName = $app->input->get('layout', 'default');
|
||||
|
||||
// legacy front-end popup view
|
||||
if ($vName === "popup") {
|
||||
// add a view path
|
||||
$this->addViewPath(JPATH_SITE . '/components/com_jce/views');
|
||||
$view = $this->getView($vName, $vFormat);
|
||||
|
||||
if ($view) {
|
||||
$view->display();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
$adminViews = array('config', 'profiles', 'profile', 'mediabox');
|
||||
|
||||
if (in_array($vName, $adminViews) && !$user->authorise('core.manage', 'com_jce')) {
|
||||
throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
|
||||
}
|
||||
|
||||
// create view
|
||||
$view = $this->getView($vName, $vFormat);
|
||||
|
||||
// Get and render the view.
|
||||
if ($view) {
|
||||
|
||||
if ($vName != "cpanel") {
|
||||
// use "profiles" for validating "profile" view
|
||||
if ($vName == "profile") {
|
||||
$vName = "profiles";
|
||||
}
|
||||
|
||||
if (!$user->authorise('jce.' . $vName, 'com_jce')) {
|
||||
throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403);
|
||||
}
|
||||
}
|
||||
|
||||
// reset view name
|
||||
$vName = $view->getName();
|
||||
|
||||
// Get the model for the view.
|
||||
$model = $this->getModel($vName, 'JceModel', array('name' => $vName));
|
||||
|
||||
// Push the model into the view (as default).
|
||||
$view->setModel($model, true);
|
||||
$view->setLayout($lName);
|
||||
|
||||
// Push document object into the view.
|
||||
$view->document = $document;
|
||||
|
||||
// only for Joomla 3.x
|
||||
if (version_compare(JVERSION, '4', 'lt')) {
|
||||
// Load the submenu.
|
||||
require_once JPATH_ADMINISTRATOR . '/components/com_jce/helpers/admin.php';
|
||||
JceHelperAdmin::addSubmenu($vName);
|
||||
}
|
||||
|
||||
$document->addStyleSheet(JURI::root(true) . '/media/com_jce/css/global.min.css?' . md5(WF_VERSION));
|
||||
|
||||
$view->display();
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
22
administrator/components/com_jce/controller/config.php
Normal file
22
administrator/components/com_jce/controller/config.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?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 JceControllerConfig extends JControllerForm
|
||||
{
|
||||
public function __construct($config = array())
|
||||
{
|
||||
parent::__construct($config);
|
||||
|
||||
// return to control panel on cancel/close
|
||||
$this->view_list = 'cpanel';
|
||||
}
|
||||
}
|
||||
26
administrator/components/com_jce/controller/cpanel.php
Normal file
26
administrator/components/com_jce/controller/cpanel.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?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 JceControllerCpanel extends JControllerLegacy
|
||||
{
|
||||
public function feed()
|
||||
{
|
||||
$model = $this->getModel('cpanel');
|
||||
|
||||
echo json_encode(array(
|
||||
'feeds' => $model->getFeeds()
|
||||
));
|
||||
|
||||
// Close the application
|
||||
JFactory::getApplication()->close();
|
||||
}
|
||||
}
|
||||
34
administrator/components/com_jce/controller/editor.php
Normal file
34
administrator/components/com_jce/controller/editor.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 3 - http://www.gnu.org/copyleft/gpl.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_SITE . '/components/com_jce/editor/libraries/classes/application.php';
|
||||
|
||||
class JceControllerEditor extends JControllerLegacy
|
||||
{
|
||||
public function execute($task)
|
||||
{
|
||||
// check for session token
|
||||
JSession::checkToken('get') or jexit(JText::_('JINVALID_TOKEN'));
|
||||
|
||||
$editor = new WFEditor();
|
||||
|
||||
if (strpos($task, '.') !== false) {
|
||||
list($name, $task) = explode('.', $task);
|
||||
}
|
||||
|
||||
if (method_exists($editor, $task)) {
|
||||
$editor->$task();
|
||||
}
|
||||
|
||||
jexit();
|
||||
}
|
||||
}
|
||||
21
administrator/components/com_jce/controller/mediabox.php
Normal file
21
administrator/components/com_jce/controller/mediabox.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?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 JceControllerMediabox extends JControllerForm
|
||||
{
|
||||
public function __construct($config = array())
|
||||
{
|
||||
parent::__construct($config);
|
||||
// return to control panel on cancel/close
|
||||
$this->view_list = 'cpanel';
|
||||
}
|
||||
}
|
||||
108
administrator/components/com_jce/controller/plugin.php
Normal file
108
administrator/components/com_jce/controller/plugin.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 3 - http://www.gnu.org/copyleft/gpl.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_SITE . '/components/com_jce/editor/libraries/classes/application.php';
|
||||
|
||||
class JceControllerPlugin extends JControllerLegacy
|
||||
{
|
||||
private static $map = array(
|
||||
'image' => 'imgmanager',
|
||||
'imagepro' => 'imgmanager_ext'
|
||||
);
|
||||
|
||||
private function createClassName($name) {
|
||||
$delim = array('-', '_');
|
||||
|
||||
$name = str_replace($delim, ' ', $name);
|
||||
|
||||
$className = 'WF' . ucwords($name) . 'Plugin';
|
||||
|
||||
// remove space
|
||||
$className = str_replace(' ', '', $className);
|
||||
|
||||
return $className;
|
||||
}
|
||||
|
||||
public function execute($task)
|
||||
{
|
||||
$wf = WFApplication::getInstance();
|
||||
|
||||
// check a valid profile exists
|
||||
$wf->getProfile() or jexit('Invalid Profile');
|
||||
|
||||
// load language files
|
||||
$language = JFactory::getLanguage();
|
||||
|
||||
$language->load('com_jce', JPATH_ADMINISTRATOR);
|
||||
|
||||
if (WF_EDITOR_PRO) {
|
||||
$language->load('com_jce_pro', JPATH_SITE);
|
||||
}
|
||||
|
||||
$plugin = $this->input->get('plugin');
|
||||
|
||||
// get plugin name
|
||||
if (strpos($plugin, '.') !== false) {
|
||||
list($plugin, $caller) = explode('.', $plugin);
|
||||
}
|
||||
|
||||
// map plugin name to internal / legacy name
|
||||
if (array_key_exists($plugin, self::$map)) {
|
||||
$plugin = self::$map[$plugin];
|
||||
$mapped = $plugin;
|
||||
|
||||
if (!empty($caller)) {
|
||||
$mapped = $plugin . '.' . $caller;
|
||||
}
|
||||
|
||||
$this->input->set('plugin', $mapped);
|
||||
}
|
||||
|
||||
$path = WF_EDITOR_PLUGINS . '/' . $plugin;
|
||||
|
||||
if (strpos($plugin, 'editor-') !== false) {
|
||||
$path = JPATH_PLUGINS . '/jce/' . $plugin;
|
||||
}
|
||||
|
||||
if (!file_exists($path . '/' . $plugin . '.php')) {
|
||||
throw new InvalidArgumentException(ucfirst($plugin) . '" not found!');
|
||||
}
|
||||
|
||||
include_once $path . '/' . $plugin . '.php';
|
||||
|
||||
$className = $this->createClassName($plugin);
|
||||
|
||||
if (class_exists($className)) {
|
||||
// load language file if any
|
||||
$language->load('plg_jce_' . basename($path), $path);
|
||||
|
||||
$instance = new $className();
|
||||
|
||||
if (strpos($task, '.') !== false) {
|
||||
list($name, $task) = explode('.', $task);
|
||||
}
|
||||
|
||||
if ($task === 'display') {
|
||||
$task = 'execute';
|
||||
}
|
||||
|
||||
// default to execute if task is not available
|
||||
if (is_callable(array($instance, $task)) === false) {
|
||||
$task = 'execute';
|
||||
}
|
||||
|
||||
$instance->$task();
|
||||
}
|
||||
|
||||
jexit();
|
||||
}
|
||||
}
|
||||
36
administrator/components/com_jce/controller/profile.php
Normal file
36
administrator/components/com_jce/controller/profile.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?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 JceControllerProfile extends JControllerForm
|
||||
{
|
||||
/**
|
||||
* The URL option for the component.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $option = 'com_jce';
|
||||
|
||||
/**
|
||||
* The URL view item variable.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $view_item = 'profile';
|
||||
|
||||
/**
|
||||
* The URL view list variable.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $view_list = 'profiles';
|
||||
}
|
||||
130
administrator/components/com_jce/controller/profiles.php
Normal file
130
administrator/components/com_jce/controller/profiles.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?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 JceControllerProfiles extends JControllerAdmin
|
||||
{
|
||||
/**
|
||||
* Method to import profile data from an XML file.
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public function import()
|
||||
{
|
||||
// Check for request forgeries
|
||||
JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
|
||||
|
||||
$app = JFactory::getApplication();
|
||||
|
||||
$model = $this->getModel();
|
||||
|
||||
$result = $model->import();
|
||||
|
||||
// Get redirect URL
|
||||
$redirect_url = JRoute::_('index.php?option=com_jce&view=profiles', false);
|
||||
|
||||
// Push message queue to session because we will redirect page by Javascript, not $app->redirect().
|
||||
// The "application.queue" is only set in redirect() method, so we must manually store it.
|
||||
$app->getSession()->set('application.queue', $app->getMessageQueue());
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
echo new JResponseJson(array('redirect' => $redirect_url), "", !$result);
|
||||
|
||||
exit();
|
||||
}
|
||||
|
||||
public function repair()
|
||||
{
|
||||
// Check for request forgeries
|
||||
JSession::checkToken('get') or jexit(JText::_('JINVALID_TOKEN'));
|
||||
|
||||
$model = $this->getModel('profiles');
|
||||
|
||||
try {
|
||||
$model->repair();
|
||||
} catch (Exception $e) {
|
||||
$this->setMessage($e->getMessage(), 'error');
|
||||
}
|
||||
|
||||
$this->setRedirect('index.php?option=com_jce&view=profiles');
|
||||
}
|
||||
|
||||
public function copy()
|
||||
{
|
||||
// Check for request forgeries
|
||||
JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
|
||||
|
||||
$user = JFactory::getUser();
|
||||
$cid = $this->input->get('cid', array(), 'array');
|
||||
|
||||
// Access checks.
|
||||
if (!$user->authorise('core.create', 'com_jce')) {
|
||||
throw new Exception(JText::_('JLIB_APPLICATION_ERROR_CREATE_NOT_PERMITTED'));
|
||||
}
|
||||
|
||||
if (empty($cid)) {
|
||||
throw new Exception(JText::_('No Item Selected'));
|
||||
} else {
|
||||
$model = $this->getModel();
|
||||
// Copy the items.
|
||||
try {
|
||||
$model->copy($cid);
|
||||
$ntext = $this->text_prefix . '_N_ITEMS_COPIED';
|
||||
$this->setMessage(JText::plural($ntext, count($cid)));
|
||||
} catch (Exception $e) {
|
||||
$this->setMessage($e->getMessage(), 'error');
|
||||
}
|
||||
}
|
||||
|
||||
$this->setRedirect('index.php?option=com_jce&view=profiles');
|
||||
}
|
||||
|
||||
public function export()
|
||||
{
|
||||
// Check for request forgeries
|
||||
JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
|
||||
|
||||
$user = JFactory::getUser();
|
||||
$ids = $this->input->get('cid', array(), 'array');
|
||||
|
||||
// Access checks.
|
||||
if (!$user->authorise('core.create', 'com_jce')) {
|
||||
throw new Exception(JText::_('JLIB_APPLICATION_ERROR_CREATE_NOT_PERMITTED'));
|
||||
}
|
||||
|
||||
if (empty($ids)) {
|
||||
throw new Exception(JText::_('No Item Selected'));
|
||||
} else {
|
||||
$model = $this->getModel();
|
||||
// Publish the items.
|
||||
if (!$model->export($ids)) {
|
||||
throw new Exception($model->getError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy for getModel.
|
||||
*
|
||||
* @param string $name The model name. Optional
|
||||
* @param string $prefix The class prefix. Optional
|
||||
* @param array $config The array of possible config values. Optional
|
||||
*
|
||||
* @return object The model
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function getModel($name = 'Profile', $prefix = 'JceModel', $config = array('ignore_request' => true))
|
||||
{
|
||||
return parent::getModel($name, $prefix, $config);
|
||||
}
|
||||
}
|
||||
61
administrator/components/com_jce/helpers/admin.php
Normal file
61
administrator/components/com_jce/helpers/admin.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* Admin helper.
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
class JceHelperAdmin
|
||||
{
|
||||
/**
|
||||
* Configure the Submenu links.
|
||||
*
|
||||
* @param string $vName The view name
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
public static function addSubmenu($vName)
|
||||
{
|
||||
$uri = (string)JUri::getInstance();
|
||||
$return = urlencode(base64_encode($uri));
|
||||
|
||||
$user = JFactory::getUser();
|
||||
|
||||
JHtmlSidebar::addEntry(
|
||||
JText::_('WF_CPANEL'),
|
||||
'index.php?option=com_jce&view=cpanel',
|
||||
$vName == 'cpanel'
|
||||
);
|
||||
|
||||
$views = array(
|
||||
'config' => 'WF_CONFIGURATION',
|
||||
'profiles' => 'WF_PROFILES',
|
||||
'browser' => 'WF_CPANEL_BROWSER',
|
||||
'mediabox' => 'WF_MEDIABOX'
|
||||
);
|
||||
|
||||
foreach($views as $key => $label) {
|
||||
|
||||
if ($key === "mediabox" && !JPluginHelper::isEnabled('system', 'jcemediabox')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($user->authorise('jce.' . $key, 'com_jce')) {
|
||||
JHtmlSidebar::addEntry(
|
||||
JText::_($label),
|
||||
'index.php?option=com_jce&view=' . $key,
|
||||
$vName == $key
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function getTemplateStylesheets()
|
||||
{
|
||||
require_once(JPATH_SITE . '/components/com_jce/editor/libraries/classes/editor.php');
|
||||
|
||||
return WFEditor::getTemplateStyleSheets();
|
||||
}
|
||||
}
|
||||
121
administrator/components/com_jce/helpers/browser.php
Normal file
121
administrator/components/com_jce/helpers/browser.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<?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;
|
||||
|
||||
abstract class WfBrowserHelper
|
||||
{
|
||||
public static function getBrowserLink($element = null, $mediatype = '', $callback = '')
|
||||
{
|
||||
$options = self::getMediaFieldOptions(array(
|
||||
'element' => $element,
|
||||
'mediatype' => $mediatype,
|
||||
'callback' => $callback,
|
||||
));
|
||||
|
||||
return $options['url'];
|
||||
}
|
||||
|
||||
public static function getMediaFieldLink($element = null, $mediatype = 'images', $callback = '')
|
||||
{
|
||||
$options = self::getMediaFieldOptions(array(
|
||||
'element' => $element,
|
||||
'mediatype' => $mediatype,
|
||||
'callback' => $callback,
|
||||
));
|
||||
|
||||
return $options['url'];
|
||||
}
|
||||
|
||||
public static function getMediaFieldOptions($options = array())
|
||||
{
|
||||
$app = JFactory::getApplication();
|
||||
$token = JFactory::getSession()->getFormToken();
|
||||
|
||||
|
||||
if (!isset($options['element'])) {
|
||||
$options['element'] = null;
|
||||
}
|
||||
|
||||
if (!isset($options['mediatype'])) {
|
||||
$options['mediatype'] = 'images';
|
||||
}
|
||||
|
||||
if (!isset($options['callback'])) {
|
||||
$options['callback'] = '';
|
||||
}
|
||||
|
||||
if (!isset($options['converted'])) {
|
||||
$options['converted'] = false;
|
||||
}
|
||||
|
||||
// set $url as empty string
|
||||
$data = array(
|
||||
'url' => '',
|
||||
'upload' => 0,
|
||||
);
|
||||
|
||||
// load editor class
|
||||
require_once JPATH_SITE . '/components/com_jce/editor/libraries/classes/application.php';
|
||||
|
||||
// get editor instance
|
||||
$wf = WFApplication::getInstance();
|
||||
|
||||
// check the current user is in a profile
|
||||
if ($wf->getProfile('browser')) {
|
||||
|
||||
// is conversion enabled?
|
||||
if ($options['converted'] && (int) $wf->getParam('browser.mediafield_conversion', 1) === 0) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$data['url'] = 'index.php?option=com_jce&task=plugin.display';
|
||||
|
||||
// add default context
|
||||
if (!isset($options['context'])) {
|
||||
$options['context'] = $wf->getContext();
|
||||
}
|
||||
|
||||
// append "caller" plugin
|
||||
if (!empty($options['plugin'])) {
|
||||
if (strpos($options['plugin'], 'browser') === false) {
|
||||
$options['plugin'] = 'browser.' . $options['plugin'];
|
||||
}
|
||||
} else {
|
||||
$options['plugin'] = 'browser';
|
||||
}
|
||||
|
||||
$options['standalone'] = 1;
|
||||
$options[$token] = 1;
|
||||
$options['client'] = $app->getClientId();
|
||||
|
||||
foreach ($options as $key => $value) {
|
||||
if ($value) {
|
||||
$data['url'] .= '&' . $key . '=' . $value;
|
||||
}
|
||||
}
|
||||
|
||||
// get allowed extensions
|
||||
$accept = $wf->getParam('browser.extensions', 'jpg,jpeg,png,gif,mp3,m4a,mp4a,ogg,mp4,mp4v,mpeg,mov,webm,doc,docx,odg,odp,ods,odt,pdf,ppt,pptx,txt,xcf,xls,xlsx,csv,zip,tar,gz');
|
||||
|
||||
$data['accept'] = array_map(function ($value) {
|
||||
if ($value[0] != '-') {
|
||||
return $value;
|
||||
}
|
||||
}, explode(',', $accept));
|
||||
|
||||
$data['accept'] = implode(',', array_filter($data['accept']));
|
||||
|
||||
$data['upload'] = (int) $wf->getParam('browser.mediafield_upload', 1);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
163
administrator/components/com_jce/helpers/commands.json
Normal file
163
administrator/components/com_jce/helpers/commands.json
Normal file
@@ -0,0 +1,163 @@
|
||||
{
|
||||
"undo": {
|
||||
"title": "WF_UNDO_TITLE",
|
||||
"description": "WF_UNDO_DESC",
|
||||
"core": 1,
|
||||
"icon": "undo",
|
||||
"row": 1,
|
||||
"editable": 0
|
||||
},
|
||||
"redo": {
|
||||
"title": "WF_REDO_TITLE",
|
||||
"description": "WF_REDO_DESC",
|
||||
"core": 1,
|
||||
"icon": "redo",
|
||||
"row": 1,
|
||||
"editable": 0
|
||||
},
|
||||
"bold": {
|
||||
"title": "WF_BOLD_TITLE",
|
||||
"description": "WF_BOLD_DESC",
|
||||
"core": 1,
|
||||
"icon": "bold",
|
||||
"row": 1,
|
||||
"editable": 0
|
||||
},
|
||||
"italic": {
|
||||
"title": "WF_ITALIC_TITLE",
|
||||
"description": "WF_ITALIC_DESC",
|
||||
"core": 1,
|
||||
"icon": "italic",
|
||||
"row": 1,
|
||||
"editable": 0
|
||||
},
|
||||
"underline": {
|
||||
"title": "WF_UNDERLINE_TITLE",
|
||||
"description": "WF_UNDERLINE_DESC",
|
||||
"core": 1,
|
||||
"icon": "underline",
|
||||
"row": 1,
|
||||
"editable": 0
|
||||
},
|
||||
"strikethrough": {
|
||||
"title": "WF_STRIKETHROUGH_TITLE",
|
||||
"description": "WF_STRIKETHROUGH_DESC",
|
||||
"core": 1,
|
||||
"icon": "strikethrough",
|
||||
"row": 1,
|
||||
"editable": 0
|
||||
},
|
||||
"justifyfull": {
|
||||
"title": "WF_JUSTIFYFULL_TITLE",
|
||||
"description": "WF_JUSTIFYFULL_DESC",
|
||||
"core": 1,
|
||||
"icon": "justifyfull",
|
||||
"row": 1,
|
||||
"editable": 0
|
||||
},
|
||||
"justifycenter": {
|
||||
"title": "WF_JUSTIFYCENTER_TITLE",
|
||||
"description": "WF_JUSTIFYCENTER_DESC",
|
||||
"core": 1,
|
||||
"icon": "justifycenter",
|
||||
"row": 1,
|
||||
"editable": 0
|
||||
},
|
||||
"justifyleft": {
|
||||
"title": "WF_JUSTIFYLEFT_TITLE",
|
||||
"description": "WF_JUSTIFYLEFT_DESC",
|
||||
"core": 1,
|
||||
"icon": "justifyleft",
|
||||
"row": 1,
|
||||
"editable": 0
|
||||
},
|
||||
"justifyright": {
|
||||
"title": "WF_JUSTIFYRIGHT_TITLE",
|
||||
"description": "WF_JUSTIFYRIGHT_DESC",
|
||||
"core": 1,
|
||||
"icon": "justifyright",
|
||||
"row": 1,
|
||||
"editable": 0
|
||||
},
|
||||
"formatselect": {
|
||||
"title": "WF_FORMATSELECT_TITLE",
|
||||
"description": "WF_FORMATSELECT_DESC",
|
||||
"core": 1,
|
||||
"icon": "formatselect",
|
||||
"row": 1,
|
||||
"editable": 0,
|
||||
"class": "list-box"
|
||||
},
|
||||
"newdocument": {
|
||||
"title": "WF_NEWDOCUMENT_TITLE",
|
||||
"description": "WF_NEWDOCUMENT_DESC",
|
||||
"core": 1,
|
||||
"icon": "newdocument",
|
||||
"row": 1,
|
||||
"editable": 0
|
||||
},
|
||||
"unlink": {
|
||||
"title": "WF_UNLINK_TITLE",
|
||||
"description": "WF_UNLINK_DESC",
|
||||
"core": 1,
|
||||
"icon": "unlink",
|
||||
"row": 4,
|
||||
"editable": 0
|
||||
},
|
||||
"indent": {
|
||||
"title": "WF_INDENT_TITLE",
|
||||
"description": "WF_INDENT_DESC",
|
||||
"core": 1,
|
||||
"icon": "indent",
|
||||
"row": 2,
|
||||
"editable": 0
|
||||
},
|
||||
"outdent": {
|
||||
"title": "WF_OUTDENT_TITLE",
|
||||
"description": "WF_OUTDENT_DESC",
|
||||
"core": 1,
|
||||
"icon": "outdent",
|
||||
"row": 2,
|
||||
"editable": 0
|
||||
},
|
||||
"blockquote": {
|
||||
"title": "WF_BLOCKQUOTE_TITLE",
|
||||
"description": "WF_BLOCKQUOTE_DESC",
|
||||
"core": 1,
|
||||
"icon": "blockquote",
|
||||
"row": 1,
|
||||
"editable": 0
|
||||
},
|
||||
"removeformat": {
|
||||
"title": "WF_REMOVEFORMAT_TITLE",
|
||||
"description": "WF_REMOVEFORMAT_DESC",
|
||||
"core": 1,
|
||||
"icon": "removeformat",
|
||||
"row": 1,
|
||||
"editable": 0
|
||||
},
|
||||
"sub": {
|
||||
"title": "WF_SUB_TITLE",
|
||||
"description": "WF_SUB_DESC",
|
||||
"core": 1,
|
||||
"icon": "sub",
|
||||
"row": 2,
|
||||
"editable": 0
|
||||
},
|
||||
"sup": {
|
||||
"title": "WF_SUP_TITLE",
|
||||
"description": "WF_SUP_DESC",
|
||||
"core": 1,
|
||||
"icon": "sup",
|
||||
"row": 2,
|
||||
"editable": 0
|
||||
},
|
||||
"visualaid": {
|
||||
"title": "WF_VISUALAID_TITLE",
|
||||
"description": "WF_VISUALAID_DESC",
|
||||
"core": 1,
|
||||
"icon": "visualaid",
|
||||
"row": 4,
|
||||
"editable": 0
|
||||
}
|
||||
}
|
||||
157
administrator/components/com_jce/helpers/encrypt.php
Normal file
157
administrator/components/com_jce/helpers/encrypt.php
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (c)2018 Ryan Demmer
|
||||
* @license GNU General Public License version 3, or later
|
||||
*
|
||||
* @since 2.7
|
||||
*/
|
||||
// Protection against direct access
|
||||
defined('JPATH_PLATFORM') or die();
|
||||
|
||||
use Defuse\Crypto\Key;
|
||||
use Defuse\Crypto\Encoding;
|
||||
use Defuse\Crypto\Crypto;
|
||||
|
||||
/**
|
||||
* Implements encrypted settings handling features.
|
||||
*/
|
||||
class JceEncryptHelper
|
||||
{
|
||||
protected static function generateKey()
|
||||
{
|
||||
$keyObject = Key::createNewRandomKey();
|
||||
$keyAscii = $keyObject->saveToAsciiSafeString();
|
||||
|
||||
$keyData = Encoding::binToHex($keyAscii);
|
||||
|
||||
$filecontents = "<?php defined('WF_EDITOR') or die(); define('WF_SERVERKEY', '$keyData'); ?>";
|
||||
$filename = JPATH_ADMINISTRATOR . '/components/com_jce/serverkey.php';
|
||||
|
||||
file_put_contents($filename, $filecontents);
|
||||
|
||||
return Key::loadFromAsciiSafeString($keyAscii);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the configured server key, automatically loading the server key storage file
|
||||
* if required.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getKey($legacy = false)
|
||||
{
|
||||
if (!defined('WF_SERVERKEY')) {
|
||||
$filename = JPATH_ADMINISTRATOR . '/components/com_jce/serverkey.php';
|
||||
|
||||
if (is_file($filename)) {
|
||||
include_once($filename);
|
||||
}
|
||||
}
|
||||
|
||||
if (defined('WF_SERVERKEY')) {
|
||||
// return key as string
|
||||
if ($legacy) {
|
||||
$key = base64_decode(WF_SERVERKEY);
|
||||
return $key;
|
||||
}
|
||||
|
||||
try {
|
||||
$keyAscii = Encoding::hexToBin(WF_SERVERKEY);
|
||||
$key = Key::loadFromAsciiSafeString($keyAscii);
|
||||
} catch(Defuse\Crypto\Exception\BadFormatException $ex) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
return self::generateKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the settings using the automatically detected preferred algorithm.
|
||||
*
|
||||
* @param $settingsINI string The raw settings INI string
|
||||
*
|
||||
* @return string The encrypted data to store in the database
|
||||
*/
|
||||
public static function encrypt($data, $key = null)
|
||||
{
|
||||
// Do we have a non-empty key to begin with?
|
||||
if (empty($key)) {
|
||||
$key = self::getKey();
|
||||
}
|
||||
|
||||
if (empty($key)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$encrypted = Crypto::encrypt($data, $key);
|
||||
|
||||
// base64encode
|
||||
$encoded = base64_encode($encrypted);
|
||||
|
||||
// add marker
|
||||
$data = '###DEFUSE###' . $encoded;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the encrypted settings and returns the plaintext INI string.
|
||||
*
|
||||
* @param $encrypted string The encrypted data
|
||||
*
|
||||
* @return string The decrypted data
|
||||
*/
|
||||
public static function decrypt($encrypted, $key = null)
|
||||
{
|
||||
$mode = substr($encrypted, 0, 12);
|
||||
|
||||
if ($mode == '###AES128###' || $mode == '###CTR128###') {
|
||||
require_once(__DIR__ . '/encrypt/aes.php');
|
||||
|
||||
$encrypted = substr($encrypted, 12);
|
||||
|
||||
$key = self::getKey(true);
|
||||
|
||||
switch ($mode) {
|
||||
case '###AES128###':
|
||||
$encrypted = base64_decode($encrypted);
|
||||
$decrypted = @WFUtilEncrypt::AESDecryptCBC($encrypted, $key, 128);
|
||||
break;
|
||||
|
||||
case '###CTR128###':
|
||||
$decrypted = @WFUtilEncrypt::AESDecryptCtr($encrypted, $key, 128);
|
||||
break;
|
||||
}
|
||||
|
||||
return rtrim($decrypted, "\0");
|
||||
}
|
||||
|
||||
if ($mode == '###DEFUSE###') {
|
||||
$key = self::getKey();
|
||||
|
||||
if (empty($key)) {
|
||||
return $encrypted;
|
||||
}
|
||||
|
||||
//get encrypted string without marker
|
||||
$encrypted = substr($encrypted, 12);
|
||||
|
||||
// base64decode
|
||||
$decoded = base64_decode($encrypted);
|
||||
|
||||
try {
|
||||
$decrypted = Crypto::decrypt($decoded, $key);
|
||||
} catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
|
||||
return $encrypted;
|
||||
}
|
||||
|
||||
return rtrim($decrypted, "\0");
|
||||
}
|
||||
|
||||
return $encrypted;
|
||||
}
|
||||
}
|
||||
548
administrator/components/com_jce/helpers/encrypt/aes.php
Normal file
548
administrator/components/com_jce/helpers/encrypt/aes.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;
|
||||
}
|
||||
}
|
||||
373
administrator/components/com_jce/helpers/plugins.json
Normal file
373
administrator/components/com_jce/helpers/plugins.json
Normal file
@@ -0,0 +1,373 @@
|
||||
{
|
||||
"article": {
|
||||
"title": "WF_ARTICLE_TITLE",
|
||||
"description": "WF_ARTICLE_DESC",
|
||||
"icon": "readmore,pagebreak",
|
||||
"editable": 1,
|
||||
"row": 4,
|
||||
"core": 1
|
||||
},
|
||||
"anchor": {
|
||||
"title": "WF_ANCHOR_TITLE",
|
||||
"description": "WF_ANCHOR_DESC",
|
||||
"core": 1,
|
||||
"icon": "anchor",
|
||||
"row": 4,
|
||||
"editable": 0
|
||||
},
|
||||
"attributes": {
|
||||
"title": "WF_ATTRIBUTES_TITLE",
|
||||
"description": "WF_ATTRIBUTES_DESC",
|
||||
"icon": "attribs",
|
||||
"editable": 0,
|
||||
"row": 4,
|
||||
"core": 1
|
||||
},
|
||||
"autosave": {
|
||||
"title": "WF_AUTOSAVE_TITLE",
|
||||
"description": "WF_AUTOSAVE_DESC",
|
||||
"icon": "autosave",
|
||||
"editable": 0,
|
||||
"row": 4,
|
||||
"core": 1
|
||||
},
|
||||
"browser": {
|
||||
"title": "WF_BROWSER_TITLE",
|
||||
"description": "WF_BROWSER_DESC",
|
||||
"icon": "",
|
||||
"editable": 1,
|
||||
"row": 0,
|
||||
"core": 1
|
||||
},
|
||||
"charmap": {
|
||||
"title": "WF_CHARMAP_TITLE",
|
||||
"description": "WF_CHARMAP_DESC",
|
||||
"icon": "charmap",
|
||||
"editable": 1,
|
||||
"row": 2,
|
||||
"core": 1
|
||||
},
|
||||
"cleanup": {
|
||||
"title": "WF_CLEANUP_TITLE",
|
||||
"description": "WF_CLEANUP_DESC",
|
||||
"icon": "cleanup",
|
||||
"editable": 0,
|
||||
"row": 1,
|
||||
"core": 1
|
||||
},
|
||||
"clipboard": {
|
||||
"title": "WF_CLIPBOARD_TITLE",
|
||||
"description": "WF_CLIPBOARD_DESC",
|
||||
"icon": "cut,copy,paste,pastetext",
|
||||
"editable": 1,
|
||||
"row": 2,
|
||||
"core": 1
|
||||
},
|
||||
"code": {
|
||||
"title": "WF_CODE_TITLE",
|
||||
"description": "WF_CODE_DESC",
|
||||
"icon": "",
|
||||
"editable": 0,
|
||||
"row": 0,
|
||||
"core": 1
|
||||
},
|
||||
"colorpicker": {
|
||||
"title": "WF_COLORPICKER_TITLE",
|
||||
"description": "WF_COLORPICKER_DESC",
|
||||
"icon": "",
|
||||
"editable": 0,
|
||||
"row": 0,
|
||||
"core": 1
|
||||
},
|
||||
"contextmenu": {
|
||||
"title": "WF_CONTEXTMENU_TITLE",
|
||||
"description": "WF_CONTEXTMENU_DESC",
|
||||
"icon": "",
|
||||
"editable": 1,
|
||||
"row": 0,
|
||||
"core": 1
|
||||
},
|
||||
"directionality": {
|
||||
"title": "WF_DIRECTIONALITY_TITLE",
|
||||
"description": "WF_DIRECTIONALITY_DESC",
|
||||
"icon": "ltr,rtl",
|
||||
"editable": 0,
|
||||
"row": 3,
|
||||
"core": 1
|
||||
},
|
||||
"format": {
|
||||
"title": "WF_FORMAT_TITLE",
|
||||
"description": "WF_FORMAT_DESC",
|
||||
"icon": "",
|
||||
"editable": 0,
|
||||
"row": 0,
|
||||
"core": 1,
|
||||
"class": "list-box"
|
||||
},
|
||||
"formatselect": {
|
||||
"title": "WF_FORMATSELECT_TITLE",
|
||||
"description": "WF_FORMATSELECT_DESC",
|
||||
"core": 1,
|
||||
"icon": "formatselect",
|
||||
"row": 1,
|
||||
"editable": 1,
|
||||
"class": "list-box"
|
||||
},
|
||||
"fontcolor": {
|
||||
"title": "WF_FONTCOLOR_TITLE",
|
||||
"description": "WF_FONTCOLOR_DESC",
|
||||
"core": 1,
|
||||
"icon": "forecolor,backcolor",
|
||||
"row": 2,
|
||||
"editable": 1,
|
||||
"class": "split-button"
|
||||
},
|
||||
"fontselect": {
|
||||
"title": "WF_FONTSELECT_TITLE",
|
||||
"description": "WF_FONTSELECT_DESC",
|
||||
"core": 1,
|
||||
"icon": "fontselect",
|
||||
"row": 2,
|
||||
"editable": 1,
|
||||
"class": "list-box"
|
||||
},
|
||||
"fontsizeselect": {
|
||||
"title": "WF_FONTSIZESELECT_TITLE",
|
||||
"description": "WF_FONTSIZESELECT_DESC",
|
||||
"core": 1,
|
||||
"icon": "fontsizeselect",
|
||||
"row": 2,
|
||||
"editable": 1,
|
||||
"class": "list-box"
|
||||
},
|
||||
"fullscreen": {
|
||||
"title": "WF_FULLSCREEN_TITLE",
|
||||
"description": "WF_FULLSCREEN_DESC",
|
||||
"icon": "fullscreen",
|
||||
"editable": 0,
|
||||
"row": 3,
|
||||
"core": 1
|
||||
},
|
||||
"help": {
|
||||
"title": "WF_HELP_TITLE",
|
||||
"description": "WF_HELP_DESC",
|
||||
"icon": "help",
|
||||
"editable": 0,
|
||||
"row": 1,
|
||||
"core": 1
|
||||
},
|
||||
"imgmanager": {
|
||||
"title": "WF_IMGMANAGER_TITLE",
|
||||
"description": "WF_IMGMANAGER_DESC",
|
||||
"icon": "imgmanager",
|
||||
"editable": 1,
|
||||
"row": 4,
|
||||
"core": 1
|
||||
},
|
||||
"joomla": {
|
||||
"title": "WF_JOOMLABUTTONS_TITLE",
|
||||
"description": "WF_JOOMLABUTTONS_DESC",
|
||||
"icon": "joomla",
|
||||
"editable": 0,
|
||||
"row": 4,
|
||||
"core": 1,
|
||||
"class": "split-button"
|
||||
},
|
||||
"langcode": {
|
||||
"title": "WF_LANGCODE_TITLE",
|
||||
"description": "WF_LANGCODE_DESC",
|
||||
"icon": "langcode",
|
||||
"editable": 0,
|
||||
"row": 4,
|
||||
"core": 1
|
||||
},
|
||||
"layer": {
|
||||
"title": "WF_LAYER_TITLE",
|
||||
"description": "WF_LAYER_DESC",
|
||||
"icon": "insertlayer,layerforward,layerbackward,layerabsolute",
|
||||
"editable": 0,
|
||||
"row": 4,
|
||||
"core": 1
|
||||
},
|
||||
"link": {
|
||||
"title": "WF_LINK_TITLE",
|
||||
"description": "WF_LINK_DESC",
|
||||
"icon": "link",
|
||||
"editable": 1,
|
||||
"row": 4,
|
||||
"core": 1,
|
||||
"class": "split-button"
|
||||
},
|
||||
"lists": {
|
||||
"title": "WF_LISTS_TITLE",
|
||||
"description": "WF_LISTS_DESC",
|
||||
"icon": "numlist,bullist",
|
||||
"editable": 1,
|
||||
"row": 2,
|
||||
"core": 1,
|
||||
"class": "split-button"
|
||||
},
|
||||
"media": {
|
||||
"title": "WF_MEDIA_TITLE",
|
||||
"description": "WF_MEDIA_DESC",
|
||||
"icon": "",
|
||||
"editable": 1,
|
||||
"row": 0,
|
||||
"core": 1
|
||||
},
|
||||
"nonbreaking": {
|
||||
"title": "WF_NONBREAKING_TITLE",
|
||||
"description": "WF_NONBREAKING_DESC",
|
||||
"icon": "nonbreaking",
|
||||
"editable": 0,
|
||||
"row": 4,
|
||||
"core": 1
|
||||
},
|
||||
"noneditable": {
|
||||
"title": "WF_NONEDITABLE_TITLE",
|
||||
"description": "WF_NONEDITABLE_DESC",
|
||||
"icon": "",
|
||||
"editable": 1,
|
||||
"row": 0,
|
||||
"core": 1
|
||||
},
|
||||
"preview": {
|
||||
"title": "WF_PREVIEW_TITLE",
|
||||
"description": "WF_PREVIEW_DESC",
|
||||
"icon": "",
|
||||
"editable": 1,
|
||||
"row": 0,
|
||||
"core": 1
|
||||
},
|
||||
"print": {
|
||||
"title": "WF_PRINT_TITLE",
|
||||
"description": "WF_PRINT_DESC",
|
||||
"icon": "print",
|
||||
"editable": 0,
|
||||
"row": 3,
|
||||
"core": 1
|
||||
},
|
||||
"searchreplace": {
|
||||
"title": "WF_SEARCHREPLACE_TITLE",
|
||||
"description": "WF_SEARCHREPLACE_DESC",
|
||||
"icon": "search",
|
||||
"editable": 0,
|
||||
"row": 2,
|
||||
"core": 1
|
||||
},
|
||||
"source": {
|
||||
"title": "WF_SOURCE_TITLE",
|
||||
"description": "WF_SOURCE_DESC",
|
||||
"icon": "",
|
||||
"editable": 1,
|
||||
"row": 0,
|
||||
"core": 1
|
||||
},
|
||||
"spellchecker": {
|
||||
"title": "WF_SPELLCHECKER_TITLE",
|
||||
"description": "WF_SPELLCHECKER_DESC",
|
||||
"icon": "spellchecker",
|
||||
"editable": 1,
|
||||
"row": 4,
|
||||
"core": 1
|
||||
},
|
||||
"style": {
|
||||
"title": "WF_STYLE_TITLE",
|
||||
"description": "WF_STYLE_DESC",
|
||||
"icon": "style",
|
||||
"editable": 0,
|
||||
"row": 4,
|
||||
"core": 1
|
||||
},
|
||||
"styleselect": {
|
||||
"title": "WF_STYLESELECT_TITLE",
|
||||
"description": "WF_STYLESELECT_DESC",
|
||||
"core": 1,
|
||||
"icon": "styleselect",
|
||||
"row": 1,
|
||||
"editable": 1,
|
||||
"class": "list-box"
|
||||
},
|
||||
"tabfocus": {
|
||||
"title": "WF_TABFOCUS_TITLE",
|
||||
"description": "WF_TABFOCUS_DESC",
|
||||
"icon": "",
|
||||
"editable": 0,
|
||||
"row": 0,
|
||||
"core": 1
|
||||
},
|
||||
"table": {
|
||||
"title": "WF_TABLE_TITLE",
|
||||
"description": "WF_TABLE_DESC",
|
||||
"icon": "table_insert,delete_table,row_props,cell_props,row_before,row_after,delete_row,col_before,col_after,delete_col,split_cells,merge_cells",
|
||||
"editable": 1,
|
||||
"row": 3,
|
||||
"core": 1
|
||||
},
|
||||
"textcase": {
|
||||
"title": "WF_TEXTCASE_TITLE",
|
||||
"description": "WF_TEXTCASE_DESC",
|
||||
"icon": "textcase",
|
||||
"editable": 0,
|
||||
"row": 4,
|
||||
"core": 1,
|
||||
"class": "split-button"
|
||||
},
|
||||
"visualchars": {
|
||||
"title": "WF_VISUALCHARS_TITLE",
|
||||
"description": "WF_VISUALCHARS_DESC",
|
||||
"icon": "visualchars",
|
||||
"editable": 0,
|
||||
"row": 4,
|
||||
"core": 1
|
||||
},
|
||||
"wordcount": {
|
||||
"title": "WF_WORDCOUNT_TITLE",
|
||||
"description": "WF_WORDCOUNT_DESC",
|
||||
"icon": "",
|
||||
"editable": 0,
|
||||
"row": 0,
|
||||
"core": 1
|
||||
},
|
||||
"reference": {
|
||||
"title": "WF_REFERENCE_TITLE",
|
||||
"description": "WF_REFERENCE_DESC",
|
||||
"icon": "cite,abbr,acronym,del,ins",
|
||||
"editable": 1,
|
||||
"row": 4,
|
||||
"core": 1
|
||||
},
|
||||
"kitchensink": {
|
||||
"title": "WF_KITCHENSINK_TITLE",
|
||||
"description": "WF_KITCHENSINK_DESC",
|
||||
"core": 1,
|
||||
"icon": "kitchensink",
|
||||
"row": 1,
|
||||
"editable": 0
|
||||
},
|
||||
"hr": {
|
||||
"title": "WF_HR_TITLE",
|
||||
"description": "WF_HR_DESC",
|
||||
"core": 1,
|
||||
"icon": "hr",
|
||||
"row": 3,
|
||||
"editable": 0
|
||||
},
|
||||
"visualblocks": {
|
||||
"title": "WF_VISUALBLOCKS_TITLE",
|
||||
"description": "WF_VISUALBLOCKS_DESC",
|
||||
"core": 1,
|
||||
"icon": "visualblocks",
|
||||
"row": 4,
|
||||
"editable": 1
|
||||
},
|
||||
"emotions": {
|
||||
"title": "WF_EMOTIONS_TITLE",
|
||||
"description": "WF_EMOTIONS_DESC",
|
||||
"core": 1,
|
||||
"icon": "emotions",
|
||||
"row": 4,
|
||||
"editable": 1,
|
||||
"class": "split-button"
|
||||
}
|
||||
}
|
||||
448
administrator/components/com_jce/helpers/plugins.php
Normal file
448
administrator/components/com_jce/helpers/plugins.php
Normal file
@@ -0,0 +1,448 @@
|
||||
<?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';
|
||||
|
||||
abstract class JcePluginsHelper
|
||||
{
|
||||
public static function getCommands()
|
||||
{
|
||||
$data = file_get_contents(__DIR__ . '/commands.json');
|
||||
$json = json_decode($data);
|
||||
|
||||
$commands = array();
|
||||
|
||||
if ($json) {
|
||||
foreach ($json as $name => $attribs) {
|
||||
$attribs->type = 'command';
|
||||
$commands[$name] = $attribs;
|
||||
}
|
||||
}
|
||||
|
||||
return $commands;
|
||||
}
|
||||
|
||||
public static function getPlugins()
|
||||
{
|
||||
$language = JFactory::getLanguage();
|
||||
|
||||
static $plugins;
|
||||
|
||||
if (!isset($plugins)) {
|
||||
$plugins = array();
|
||||
|
||||
// get core json
|
||||
$core = file_get_contents(__DIR__ . '/plugins.json');
|
||||
// decode to object
|
||||
$data = json_decode($core);
|
||||
|
||||
if ($data) {
|
||||
foreach ($data as $name => $attribs) {
|
||||
// skip if the plugin file is missing
|
||||
if (!is_file(WF_EDITOR_PLUGINS . '/' . $name . '/editor_plugin.js')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// update attributes
|
||||
$attribs->type = 'plugin';
|
||||
|
||||
$attribs->path = WF_EDITOR_PLUGINS . '/' . $name;
|
||||
$attribs->manifest = WF_EDITOR_PLUGINS . '/' . $name . '/' . $name . '.xml';
|
||||
|
||||
$attribs->image = '';
|
||||
|
||||
if (!isset($attribs->class)) {
|
||||
$attribs->class = '';
|
||||
}
|
||||
|
||||
// compatability
|
||||
$attribs->name = $name;
|
||||
// pass to array
|
||||
$plugins[$name] = $attribs;
|
||||
}
|
||||
}
|
||||
// get pro json
|
||||
if (is_file(__DIR__ . '/pro.json')) {
|
||||
$pro = @file_get_contents(__DIR__ . '/pro.json');
|
||||
// decode to object
|
||||
if ($pro) {
|
||||
$data = json_decode($pro);
|
||||
|
||||
if ($data) {
|
||||
foreach ($data as $name => $attribs) {
|
||||
// skip if the plugin file is missing
|
||||
if (!is_file(WF_EDITOR_PLUGINS . '/' . $name . '/editor_plugin.js')) {
|
||||
continue;
|
||||
}
|
||||
// update attributes
|
||||
$attribs->type = 'plugin';
|
||||
$attribs->path = WF_EDITOR_PLUGINS . '/' . $name;
|
||||
$attribs->manifest = WF_EDITOR_PLUGINS . '/' . $name . '/' . $name . '.xml';
|
||||
|
||||
$attribs->image = '';
|
||||
|
||||
if (!isset($attribs->class)) {
|
||||
$attribs->class = '';
|
||||
}
|
||||
|
||||
// compatability
|
||||
$attribs->name = $name;
|
||||
// pass to array
|
||||
$plugins[$name] = $attribs;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get all installed plugins
|
||||
$installed = JPluginHelper::getPlugin('jce');
|
||||
|
||||
foreach ($installed as $item) {
|
||||
// check for delimiter, only load editor plugins
|
||||
if (strpos($item->name, 'editor-') === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// create path
|
||||
$path = JPATH_PLUGINS . '/jce/' . $item->name;
|
||||
|
||||
// load language
|
||||
$language->load('plg_jce_' . $item->name, JPATH_ADMINISTRATOR);
|
||||
$language->load('plg_jce_' . $item->name, $path);
|
||||
|
||||
// get xml file
|
||||
$file = $path . '/' . $item->name . '.xml';
|
||||
|
||||
if (is_file($file)) {
|
||||
// load xml data
|
||||
$xml = simplexml_load_file($file);
|
||||
|
||||
if ($xml) {
|
||||
// check xml file is valid
|
||||
if ((string)$xml->getName() != 'extension') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check for editor_plugins.js file
|
||||
if (!is_file($path . '/editor_plugin.js')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$name = str_replace('editor-', '', $item->name);
|
||||
|
||||
$attribs = new StdClass();
|
||||
$attribs->name = $name;
|
||||
$attribs->manifest = $file;
|
||||
|
||||
$params = $xml->fields;
|
||||
|
||||
$attribs->title = (string)$xml->name;
|
||||
$attribs->icon = (string)$xml->icon;
|
||||
$attribs->editable = 0;
|
||||
|
||||
// set default values
|
||||
$attribs->image = '';
|
||||
$attribs->class = '';
|
||||
|
||||
if ($xml->icon->attributes()) {
|
||||
foreach($xml->icon->attributes() as $key => $value) {
|
||||
$attribs->$key = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if ($attribs->image) {
|
||||
$attribs->image = JURI::root(true) . '/' . $attribs->image;
|
||||
}
|
||||
|
||||
// can't be editable without parameters
|
||||
if ($params && count($params->children())) {
|
||||
$attribs->editable = 1;
|
||||
}
|
||||
|
||||
$row = (int)$xml->attributes()->row;
|
||||
|
||||
// set row from passed in value or 0
|
||||
$attribs->row = $row;
|
||||
|
||||
// if an icon is set and no row, default to 4
|
||||
if (!empty($attribs->icon) && !$row) {
|
||||
$attribs->row = 4;
|
||||
}
|
||||
|
||||
$attribs->description = (string)$xml->description;
|
||||
$attribs->core = 0;
|
||||
|
||||
// relative path
|
||||
$attribs->path = $path;
|
||||
$attribs->url = 'plugins/jce/' . $item->name;
|
||||
$attribs->type = 'plugin';
|
||||
|
||||
$plugins[$name] = $attribs;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get installed extensions.
|
||||
*
|
||||
* @return array $extensions
|
||||
*/
|
||||
public static function getExtensions($type = '')
|
||||
{
|
||||
jimport('joomla.filesystem.folder');
|
||||
jimport('joomla.filesystem.file');
|
||||
|
||||
$language = JFactory::getLanguage();
|
||||
|
||||
static $extensions;
|
||||
|
||||
if (empty($extensions)) {
|
||||
$extensions = array();
|
||||
|
||||
// recursively get all extension files
|
||||
$files = JFolder::files(WF_EDITOR_EXTENSIONS, '\.xml$', true, true);
|
||||
|
||||
foreach ($files as $file) {
|
||||
$name = basename($file, '.xml');
|
||||
|
||||
$object = new StdClass();
|
||||
$object->folder = basename(dirname($file));
|
||||
$object->manifest = $file;
|
||||
$object->plugins = array();
|
||||
$object->name = $name;
|
||||
$object->title = 'WF_' . strtoupper($object->folder) . '_' . strtoupper($name) . '_TITLE';
|
||||
$object->description = '';
|
||||
$object->id = $object->folder . '.' . $object->name;
|
||||
$object->extension = $object->name;
|
||||
// set as non-core by default
|
||||
$object->core = 0;
|
||||
// set as not editable by default
|
||||
$object->editable = 0;
|
||||
// set type
|
||||
$object->type = $object->folder;
|
||||
|
||||
$extensions[$object->type][] = $object;
|
||||
}
|
||||
|
||||
// get all installed plugins
|
||||
$installed = JPluginHelper::getPlugin('jce');
|
||||
|
||||
if (!empty($installed)) {
|
||||
foreach ($installed as $p) {
|
||||
|
||||
// check for delimiter
|
||||
if (strpos($p->name, '-') === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// only load "extensions", not editor plugins
|
||||
if (strpos($p->name, 'editor-') !== false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// set path
|
||||
$p->path = JPATH_PLUGINS . '/jce/' . $p->name;
|
||||
|
||||
$parts = explode('-', $p->name);
|
||||
|
||||
// get type and name
|
||||
$p->folder = $parts[0];
|
||||
$p->extension = $parts[1];
|
||||
|
||||
// plugin manifest, eg: filesystem-joomla.xml
|
||||
$p->manifest = $p->path . '/' . $p->name . '.xml';
|
||||
|
||||
$p->plugins = array();
|
||||
$p->description = '';
|
||||
|
||||
list($p->type, $p->name) = preg_split('/-/', $p->name);
|
||||
|
||||
// create title from name parts, eg: plg_jce_filesystem_joomla
|
||||
$p->title = 'plg_jce_' . $p->type . '_' . $p->name;
|
||||
|
||||
// create plugin id, eg: filesystem.joomla
|
||||
$p->id = $p->type . '.' . $p->name;
|
||||
|
||||
// not core
|
||||
$p->core = 0;
|
||||
|
||||
// set as not editable by default
|
||||
$p->editable = 0;
|
||||
|
||||
// load language
|
||||
$language->load('plg_jce_' . $p->type . '-' . $p->name, JPATH_ADMINISTRATOR);
|
||||
$language->load('plg_jce_' . $p->type . '-' . $p->name, $p->path);
|
||||
|
||||
$extensions[$p->type][] = $p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($type && isset($extensions[$type])) {
|
||||
return $extensions[$type];
|
||||
}
|
||||
|
||||
return $extensions;
|
||||
}
|
||||
|
||||
public static function addToProfile($id, $plugin)
|
||||
{
|
||||
JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_jce/tables');
|
||||
|
||||
// Add to Default Group
|
||||
$profile = JTable::getInstance('Profiles', 'JceTable');
|
||||
|
||||
if ($profile->load($id)) {
|
||||
// Add to plugins list
|
||||
$plugins = explode(',', $profile->plugins);
|
||||
|
||||
if (!in_array($plugin->name, $plugins)) {
|
||||
$plugins[] = $plugin->name;
|
||||
}
|
||||
|
||||
$profile->plugins = implode(',', $plugins);
|
||||
|
||||
if ($plugin->icon) {
|
||||
if (in_array($plugin->name, preg_split('/[;,]+/', $profile->rows)) === false) {
|
||||
// get rows as array
|
||||
$rows = explode(';', $profile->rows);
|
||||
|
||||
if (count($rows)) {
|
||||
// get key (row number)
|
||||
$key = count($rows) - 1;
|
||||
// get row contents as array
|
||||
$row = explode(',', $rows[$key]);
|
||||
// add plugin name to end of row
|
||||
$row[] = $plugin->name;
|
||||
// add row data back to rows array
|
||||
$rows[$key] = implode(',', $row);
|
||||
|
||||
$profile->rows = implode(';', $rows);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$profile->store()) {
|
||||
throw new Exception(JText::_('WF_INSTALLER_PLUGIN_PROFILE_ERROR'));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function removeFromProfile($id, $plugin)
|
||||
{
|
||||
JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_jce/tables');
|
||||
|
||||
// Add to Default Group
|
||||
$profile = JTable::getInstance('Profiles', 'JceTable');
|
||||
|
||||
if ($profile->load($id)) {
|
||||
// remove from plugins list
|
||||
$plugins = explode(',', $profile->plugins);
|
||||
$key = array_search($plugin->name, $plugins);
|
||||
|
||||
if ($key) {
|
||||
unset($plugins[$key]);
|
||||
$profile->plugins = implode(',', array_values($plugins));
|
||||
}
|
||||
|
||||
if ($plugin->icon) {
|
||||
// check if its in the profile
|
||||
if (in_array($plugin->name, preg_split('/[;,]+/', $profile->rows))) {
|
||||
$lists = array();
|
||||
foreach (explode(';', $profile->rows) as $list) {
|
||||
$icons = explode(',', $list);
|
||||
foreach ($icons as $k => $v) {
|
||||
if ($plugin->name == $v) {
|
||||
unset($icons[$k]);
|
||||
}
|
||||
}
|
||||
$lists[] = implode(',', $icons);
|
||||
}
|
||||
$profile->rows = implode(';', $lists);
|
||||
}
|
||||
|
||||
if (!$profile->store()) {
|
||||
throw new Exception(JText::sprintf('WF_INSTALLER_REMOVE_FROM_GROUP_ERROR', $plugin->name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add index.html files to each folder.
|
||||
*/
|
||||
private static function addIndexfiles($path)
|
||||
{
|
||||
jimport('joomla.filesystem.folder');
|
||||
jimport('joomla.filesystem.file');
|
||||
|
||||
// get the base file
|
||||
$file = JPATH_ADMINISTRATOR . '/components/com_jce/index.html';
|
||||
|
||||
if (is_file($file) && is_dir($path)) {
|
||||
JFile::copy($file, $path . '/' . basename($file));
|
||||
|
||||
// admin component
|
||||
$folders = JFolder::folders($path, '.', true, true);
|
||||
|
||||
foreach ($folders as $folder) {
|
||||
JFile::copy($file, $folder . '/' . basename($file));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function postInstall($route, $plugin, $installer)
|
||||
{
|
||||
$db = JFactory::getDBO();
|
||||
|
||||
jimport('joomla.filesystem.folder');
|
||||
|
||||
// load the plugin and enable
|
||||
if (isset($plugin->row) && $plugin->row > 0) {
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
$query->select('id')->from('#__wf_profiles')->where('name = ' . $db->Quote('Default') . ' OR id = 1');
|
||||
|
||||
$db->setQuery($query);
|
||||
$id = $db->loadResult();
|
||||
|
||||
if ($id) {
|
||||
if ($route == 'install') {
|
||||
// add to profile
|
||||
self::addToProfile($id, $plugin);
|
||||
} else {
|
||||
// remove from profile
|
||||
self::removeFromProfile($id, $plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($route == 'install') {
|
||||
if ($plugin->type == 'extension') {
|
||||
$plugin->path = $plugin->path . '/' . $plugin->name;
|
||||
}
|
||||
|
||||
// add index.html files
|
||||
self::addIndexfiles($plugin->path);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
416
administrator/components/com_jce/helpers/profiles.php
Normal file
416
administrator/components/com_jce/helpers/profiles.php
Normal file
@@ -0,0 +1,416 @@
|
||||
<?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;
|
||||
|
||||
abstract class JceProfilesHelper
|
||||
{
|
||||
|
||||
/**
|
||||
* Create the Profiles table.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function createProfilesTable()
|
||||
{
|
||||
jimport('joomla.installer.helper');
|
||||
|
||||
$app = JFactory::getApplication();
|
||||
|
||||
$db = JFactory::getDBO();
|
||||
$driver = strtolower($db->name);
|
||||
|
||||
switch ($driver) {
|
||||
default:
|
||||
case 'mysql':
|
||||
case 'mysqli':
|
||||
$driver = 'mysql';
|
||||
break;
|
||||
case 'sqlsrv':
|
||||
case 'sqlazure':
|
||||
case 'sqlzure':
|
||||
$driver = 'sqlsrv';
|
||||
break;
|
||||
case 'postgresql':
|
||||
case 'pgsql':
|
||||
$driver = 'postgresql';
|
||||
break;
|
||||
}
|
||||
|
||||
$file = JPATH_ADMINISTRATOR . '/components/com_jce/sql/' . $driver . '.sql';
|
||||
$error = null;
|
||||
|
||||
if (is_file($file)) {
|
||||
$query = file_get_contents($file);
|
||||
|
||||
if ($query) {
|
||||
// replace prefix
|
||||
$query = $db->replacePrefix((string) $query);
|
||||
|
||||
// set query
|
||||
$db->setQuery(trim($query));
|
||||
|
||||
if (!$db->execute()) {
|
||||
$app->enqueueMessage(JText::_('WF_INSTALL_TABLE_PROFILES_ERROR') . $db->stdErr(), 'error');
|
||||
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
$error = 'NO SQL QUERY';
|
||||
}
|
||||
} else {
|
||||
$error = 'SQL FILE MISSING';
|
||||
}
|
||||
|
||||
$app->enqueueMessage(JText::_('WF_INSTALL_TABLE_PROFILES_ERROR') . !is_null($error) ? ' - ' . $error : '', 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Install Profiles.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @param object $install[optional]
|
||||
*/
|
||||
public static function installProfiles()
|
||||
{
|
||||
$app = JFactory::getApplication();
|
||||
$db = JFactory::getDBO();
|
||||
|
||||
if (self::createProfilesTable()) {
|
||||
self::buildCountQuery();
|
||||
|
||||
$profiles = array('Default' => false, 'Front End' => false);
|
||||
|
||||
// No Profiles table data
|
||||
if (!$db->loadResult()) {
|
||||
$xml = JPATH_ADMINISTRATOR . '/components/com_jce/models/profiles.xml';
|
||||
|
||||
if (is_file($xml)) {
|
||||
if (!self::processImport($xml)) {
|
||||
$app->enqueueMessage(JText::_('WF_INSTALL_PROFILES_ERROR'), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$app->enqueueMessage(JText::_('WF_INSTALL_PROFILES_NOFILE_ERROR'), 'error');
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static function buildCountQuery($name = '')
|
||||
{
|
||||
$db = JFactory::getDBO();
|
||||
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
// check for name
|
||||
$query->select('COUNT(id)')->from('#__wf_profiles');
|
||||
|
||||
if ($name) {
|
||||
$query->where('name = ' . $db->Quote($name));
|
||||
}
|
||||
|
||||
$db->setQuery($query);
|
||||
}
|
||||
|
||||
public static function getDefaultProfile()
|
||||
{
|
||||
$mainframe = JFactory::getApplication();
|
||||
$file = JPATH_ADMINISTRATOR . '/components/com_jce/models/profiles.xml';
|
||||
|
||||
$xml = simplexml_load_file($file);
|
||||
|
||||
JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_jce/tables');
|
||||
|
||||
if ($xml) {
|
||||
foreach ($xml->profiles->children() as $profile) {
|
||||
if ($profile->attributes()->default) {
|
||||
$table = JTable::getInstance('Profiles', 'JceTable');
|
||||
|
||||
foreach ($profile->children() as $item) {
|
||||
switch ($item->getName()) {
|
||||
case 'rows':
|
||||
$table->rows = (string) $item;
|
||||
break;
|
||||
case 'plugins':
|
||||
$table->plugins = (string) $item;
|
||||
break;
|
||||
default:
|
||||
$key = $item->getName();
|
||||
$table->$key = (string) $item;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// reset name and description
|
||||
$table->name = '';
|
||||
$table->description = '';
|
||||
|
||||
return $table;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a table exists.
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @param string $table Table name
|
||||
*/
|
||||
public static function checkTable()
|
||||
{
|
||||
$db = JFactory::getDBO();
|
||||
|
||||
$tables = $db->getTableList();
|
||||
|
||||
if (!empty($tables)) {
|
||||
// swap array values with keys, convert to lowercase and return array keys as values
|
||||
$tables = array_keys(array_change_key_case(array_flip($tables)));
|
||||
$app = JFactory::getApplication();
|
||||
$match = str_replace('#__', strtolower($app->getCfg('dbprefix', '')), '#__wf_profiles');
|
||||
|
||||
return in_array($match, $tables);
|
||||
}
|
||||
|
||||
// try with query
|
||||
self::buildCountQuery();
|
||||
|
||||
return $db->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check table contents.
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @param string $table Table name
|
||||
*/
|
||||
public static function checkTableContents()
|
||||
{
|
||||
$db = JFactory::getDBO();
|
||||
|
||||
self::buildCountQuery();
|
||||
|
||||
return $db->loadResult();
|
||||
}
|
||||
|
||||
public static function getUserGroups($area)
|
||||
{
|
||||
$db = JFactory::getDBO();
|
||||
|
||||
jimport('joomla.access.access');
|
||||
|
||||
$query = $db->getQuery(true);
|
||||
|
||||
$query->select('id')->from('#__usergroups');
|
||||
|
||||
$db->setQuery($query);
|
||||
$groups = $db->loadColumn();
|
||||
|
||||
$front = array();
|
||||
$back = array();
|
||||
|
||||
foreach ($groups as $group) {
|
||||
$create = JAccess::checkGroup($group, 'core.create');
|
||||
$admin = JAccess::checkGroup($group, 'core.login.admin');
|
||||
$super = JAccess::checkGroup($group, 'core.admin');
|
||||
|
||||
if ($super) {
|
||||
$back[] = $group;
|
||||
} else {
|
||||
// group can create
|
||||
if ($create) {
|
||||
// group has admin access
|
||||
if ($admin) {
|
||||
$back[] = $group;
|
||||
} else {
|
||||
$front[] = $group;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch ($area) {
|
||||
case 0:
|
||||
return array_merge($front, $back);
|
||||
break;
|
||||
case 1:
|
||||
return $front;
|
||||
break;
|
||||
case 2:
|
||||
return $back;
|
||||
break;
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process import data from XML file.
|
||||
*
|
||||
* @param object $file XML file
|
||||
* @param bool $install Can be used by the package installer
|
||||
*/
|
||||
public static function processImport($file)
|
||||
{
|
||||
$n = 0;
|
||||
|
||||
$app = JFactory::getApplication();
|
||||
|
||||
// load data from file
|
||||
$data = file_get_contents($file);
|
||||
// format params data as CDATA
|
||||
$data = preg_replace('#<params>{(.+?)}<\/params>#', '<params><![CDATA[{$1}]]></params>', $data);
|
||||
// load processed string
|
||||
$xml = simplexml_load_string($data);
|
||||
|
||||
$user = JFactory::getUser();
|
||||
$date = new JDate();
|
||||
|
||||
JTable::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_jce/tables');
|
||||
|
||||
$language = JFactory::getLanguage();
|
||||
$language->load('com_jce', JPATH_ADMINISTRATOR, null, true);
|
||||
|
||||
if ($xml) {
|
||||
foreach ($xml->profiles->children() as $profile) {
|
||||
$table = JTable::getInstance('Profiles', 'JceTable');
|
||||
|
||||
foreach ($profile->children() as $item) {
|
||||
$key = $item->getName();
|
||||
$value = (string) $item;
|
||||
|
||||
switch ($key) {
|
||||
case 'name':
|
||||
// only if name set and table name not set
|
||||
if ($value) {
|
||||
// create name copy if exists
|
||||
while ($table->load(array('name' => $value))) {
|
||||
if ($value === $table->name) {
|
||||
$value = Joomla\String\StringHelper::increment($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'description':
|
||||
$value = JText::_($value);
|
||||
break;
|
||||
case 'types':
|
||||
|
||||
if ($value === "") {
|
||||
$area = (string) $profile->area[0] || 0;
|
||||
$groups = self::getUserGroups($area);
|
||||
$value = implode(',', array_unique($groups));
|
||||
}
|
||||
break;
|
||||
case 'users':
|
||||
break;
|
||||
case 'area':
|
||||
if ($value === "") {
|
||||
$value = '0';
|
||||
}
|
||||
|
||||
break;
|
||||
case 'components':
|
||||
break;
|
||||
case 'params':
|
||||
if (!empty($value)) {
|
||||
$data = json_decode($value, true);
|
||||
|
||||
if (is_array($data)) {
|
||||
array_walk($data, function (&$param, $key) {
|
||||
if (is_string($param) && WFUtility::isJson($param)) {
|
||||
$param = json_decode($param, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$value = json_encode($data);
|
||||
}
|
||||
|
||||
if (empty($value)) {
|
||||
$value = "{}";
|
||||
}
|
||||
|
||||
break;
|
||||
case 'rows':
|
||||
break;
|
||||
case 'plugins':
|
||||
break;
|
||||
case 'area':
|
||||
case 'published':
|
||||
case 'ordering':
|
||||
$value = (int) $value;
|
||||
break;
|
||||
}
|
||||
|
||||
$table->$key = $value;
|
||||
}
|
||||
|
||||
// set new id
|
||||
$table->id = 0;
|
||||
|
||||
// set checked_out
|
||||
$table->checked_out = $user->get('id');
|
||||
|
||||
// set checked_out_time
|
||||
$table->checked_out_time = $date->toSQL();
|
||||
|
||||
if (!$table->store()) {
|
||||
$app->enqueueMessage($table->getError(), 'error');
|
||||
return false;
|
||||
}
|
||||
|
||||
// check-in
|
||||
$table->checkin();
|
||||
|
||||
++$n;
|
||||
}
|
||||
}
|
||||
|
||||
return $n;
|
||||
}
|
||||
|
||||
/**
|
||||
* CDATA encode a parameter if it contains & < > characters, eg: <![CDATA[index.php?option=com_content&view=article&id=1]]>.
|
||||
*
|
||||
* @param object $param
|
||||
*
|
||||
* @return CDATA encoded parameter or parameter
|
||||
*/
|
||||
public static function encodeData($data)
|
||||
{
|
||||
if (preg_match('/[<>&]/', $data)) {
|
||||
$data = '<![CDATA[' . $data . ']]>';
|
||||
}
|
||||
|
||||
$data = preg_replace('/"/', '\"', $data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
68
administrator/components/com_jce/includes/base.php
Normal file
68
administrator/components/com_jce/includes/base.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?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;
|
||||
|
||||
// load constants
|
||||
require_once __DIR__ . '/constants.php';
|
||||
|
||||
// register classes
|
||||
JLoader::register('WFApplication', WF_EDITOR_CLASSES . '/application.php');
|
||||
JLoader::register('WFEditor', WF_EDITOR_CLASSES . '/editor.php');
|
||||
JLoader::register('WFEditorPlugin', WF_EDITOR_CLASSES . '/plugin.php');
|
||||
|
||||
JLoader::register('WFLanguage', WF_EDITOR_CLASSES . '/language.php');
|
||||
JLoader::register('WFUtility', WF_EDITOR_CLASSES . '/utility.php');
|
||||
JLoader::register('WFMimeType', WF_EDITOR_CLASSES . '/mime.php');
|
||||
|
||||
JLoader::register('WFDocument', WF_EDITOR_CLASSES . '/document.php');
|
||||
JLoader::register('WFTabs', WF_EDITOR_CLASSES . '/tabs.php');
|
||||
JLoader::register('WFView', WF_EDITOR_CLASSES . '/view.php');
|
||||
|
||||
JLoader::register('WFRequest', WF_EDITOR_CLASSES . '/request.php');
|
||||
JLoader::register('WFResponse', WF_EDITOR_CLASSES . '/response.php');
|
||||
|
||||
JLoader::register('WFLanguageParser', WF_EDITOR_CLASSES . '/languageparser.php');
|
||||
JLoader::register('WFPacker', WF_EDITOR_CLASSES . '/packer.php');
|
||||
|
||||
JLoader::register('WFExtension', WF_EDITOR_CLASSES . '/extensions.php');
|
||||
JLoader::register('WFFileSystem', WF_EDITOR_CLASSES . '/extensions/filesystem.php');
|
||||
JLoader::register('WFLinkExtension', WF_EDITOR_CLASSES . '/extensions/link.php');
|
||||
JLoader::register('WFAggregatorExtension', WF_EDITOR_CLASSES . '/extensions/aggregator.php');
|
||||
JLoader::register('WFMediaPlayerExtension', WF_EDITOR_CLASSES . '/extensions/mediaplayer.php');
|
||||
JLoader::register('WFPopupsExtension', WF_EDITOR_CLASSES . '/extensions/popups.php');
|
||||
JLoader::register('WFSearchExtension', WF_EDITOR_CLASSES . '/extensions/search.php');
|
||||
|
||||
JLoader::register('WFMediaManagerBase', WF_EDITOR_CLASSES . '/manager/base.php');
|
||||
JLoader::register('WFMediaManager', WF_EDITOR_CLASSES . '/manager.php');
|
||||
JLoader::register('WFFileBrowser', WF_EDITOR_CLASSES . '/browser.php');
|
||||
JLoader::register('Wf_Mobile_Detect', WF_EDITOR_CLASSES . '/mobile.php');
|
||||
|
||||
JLoader::register('JcePluginsHelper', WF_ADMINISTRATOR . '/helpers/plugins.php');
|
||||
JLoader::register('JceEncryptHelper', WF_ADMINISTRATOR . '/helpers/encrypt.php');
|
||||
|
||||
JLoader::register('WFLinkHelper', WF_EDITOR_CLASSES . '/linkhelper.php');
|
||||
|
||||
// Defuse
|
||||
JLoader::registerNamespace('Defuse\\Crypto', WF_ADMINISTRATOR . '/vendor/Defuse/Crypto', false, false, 'psr4');
|
||||
|
||||
// CssMin
|
||||
JLoader::registerNamespace('tubalmartin\CssMin', WF_EDITOR_CLASSES . '/vendor/cssmin/src', false, false, 'psr4');
|
||||
|
||||
// legacy class for backwards compatability
|
||||
JLoader::register('WFText', WF_EDITOR_CLASSES . '/text.php');
|
||||
|
||||
// legacy class for backwards compatability
|
||||
JLoader::register('WFModelEditor', WF_ADMINISTRATOR . '/models/editor.php');
|
||||
|
||||
// legacy function prevent fatal errors in 3rd party extensions
|
||||
function wfimport($path = ""){
|
||||
return true;
|
||||
}
|
||||
46
administrator/components/com_jce/includes/constants.php
Normal file
46
administrator/components/com_jce/includes/constants.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?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');
|
||||
|
||||
// Some shortcuts to make life easier
|
||||
define('WF_VERSION', '2.9.32');
|
||||
|
||||
// JCE Administration Component
|
||||
define('WF_ADMINISTRATOR', JPATH_ADMINISTRATOR.'/components/com_jce');
|
||||
// JCE Site Component
|
||||
define('WF_SITE', JPATH_SITE.'/components/com_jce');
|
||||
// JCE Plugin
|
||||
if (defined('JPATH_PLATFORM')) {
|
||||
define('WF_PLUGIN', JPATH_SITE.'/plugins/editors/jce');
|
||||
} else {
|
||||
define('WF_PLUGIN', JPATH_SITE.'/plugins/editors');
|
||||
}
|
||||
// JCE Editor
|
||||
define('WF_EDITOR', WF_SITE.'/editor');
|
||||
// JCE Editor Plugins
|
||||
define('WF_EDITOR_PLUGINS', WF_EDITOR.'/tiny_mce/plugins');
|
||||
// JCE Editor Themes
|
||||
define('WF_EDITOR_THEMES', WF_EDITOR.'/tiny_mce/themes');
|
||||
// JCE Editor Libraries
|
||||
define('WF_EDITOR_LIBRARIES', WF_EDITOR.'/libraries');
|
||||
// JCE Editor Classes
|
||||
define('WF_EDITOR_CLASSES', WF_EDITOR_LIBRARIES.'/classes');
|
||||
// JCE Editor Extensions
|
||||
define('WF_EDITOR_EXTENSIONS', WF_EDITOR.'/extensions');
|
||||
|
||||
define('WF_EDITOR_URI', JURI::root(true) . '/components/com_jce/editor');
|
||||
|
||||
define('WF_EDITOR_PRO', '0');
|
||||
|
||||
// required for some plugins
|
||||
if (!defined('DS')) {
|
||||
define('DS', DIRECTORY_SEPARATOR);
|
||||
}
|
||||
1
administrator/components/com_jce/index.html
Normal file
1
administrator/components/com_jce/index.html
Normal file
@@ -0,0 +1 @@
|
||||
<html><body bgcolor="#FFFFFF"></body></html>
|
||||
40
administrator/components/com_jce/jce.php
Normal file
40
administrator/components/com_jce/jce.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2009-2022 Ryan Demmer. All rights reserved
|
||||
* @license GNU/GPL 3 - http://www.gnu.org/copyleft/gpl.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;
|
||||
|
||||
// define admin base path
|
||||
define('WF_ADMIN', __DIR__);
|
||||
|
||||
$app = JFactory::getApplication();
|
||||
|
||||
// throw exception for legacy task
|
||||
if ($app->input->get('task') === 'plugin') {
|
||||
throw new Exception('Restricted', 403);
|
||||
}
|
||||
|
||||
$vName = $app->input->get('view');
|
||||
|
||||
// fix legacy plugin url
|
||||
if ($vName == 'editor' && $app->input->get('layout') == 'plugin') {
|
||||
|
||||
if ($app->input->get('plugin')) {
|
||||
$app->input->set('task', 'plugin.display');
|
||||
}
|
||||
|
||||
$app->input->set('view', '');
|
||||
}
|
||||
|
||||
// constants and autoload
|
||||
require_once __DIR__ . '/includes/base.php';
|
||||
|
||||
$controller = JControllerLegacy::getInstance('Jce', array('base_path' => __DIR__));
|
||||
|
||||
$controller->execute($app->input->get('task'));
|
||||
$controller->redirect();
|
||||
80
administrator/components/com_jce/jce.xml
Normal file
80
administrator/components/com_jce/jce.xml
Normal file
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<extension type="component" version="3.9" method="upgrade">
|
||||
<name>COM_JCE</name>
|
||||
<author>Ryan Demmer</author>
|
||||
<creationDate>01-11-2022</creationDate>
|
||||
<copyright>Copyright (C) 2006 - 2022 Ryan Demmer. All rights reserved</copyright>
|
||||
<license>GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html</license>
|
||||
<authorEmail>info@joomlacontenteditor.net</authorEmail>
|
||||
<authorUrl>www.joomlacontenteditor.net</authorUrl>
|
||||
<version>2.9.32</version>
|
||||
<description>COM_JCE_XML_DESCRIPTION</description>
|
||||
|
||||
<files folder="components/com_jce">
|
||||
<folder>editor</folder>
|
||||
<folder>views</folder>
|
||||
<!--file>index.html</file-->
|
||||
<file>jce.php</file>
|
||||
<file>licence.txt</file>
|
||||
</files>
|
||||
|
||||
<!-- Component Media -->
|
||||
<media folder="media/com_jce" destination="com_jce">
|
||||
<folder>css</folder>
|
||||
<folder>img</folder>
|
||||
<folder>js</folder>
|
||||
</media>
|
||||
|
||||
<languages folder="language/en-GB">
|
||||
<language tag="en-GB">en-GB.com_jce.ini</language>
|
||||
|
||||
</languages>
|
||||
|
||||
<!-- SQL query files to execute on installation -->
|
||||
<install>
|
||||
<sql>
|
||||
<file charset="utf8" driver="mysql">sql/mysql.sql</file>
|
||||
<file charset="utf8" driver="mysqli">sql/mysql.sql</file>
|
||||
<file charset="utf8" driver="sqlsrv">sql/sqlsrv.sql</file>
|
||||
<file charset="utf8" driver="sqlzure">sql/sqlsrv.sql</file>
|
||||
<file charset="utf8" driver="sqlazure">sql/sqlsrv.sql</file>
|
||||
<file charset="utf8" driver="postgresql">sql/postgresql.sql</file>
|
||||
<file charset="utf8" driver="pgsql">sql/postgresql.sql</file>
|
||||
</sql>
|
||||
</install>
|
||||
|
||||
<administration>
|
||||
<menu view="cpanel" link="option=com_jce">COM_JCE</menu>
|
||||
|
||||
<submenu>
|
||||
<menu view="cpanel" link="option=com_jce&view=cpanel">COM_JCE_MENU_CPANEL</menu>
|
||||
<menu view="config" link="option=com_jce&view=config">COM_JCE_MENU_CONFIG</menu>
|
||||
<menu view="profiles" link="option=com_jce&view=profiles">COM_JCE_MENU_PROFILES</menu>
|
||||
<menu view="profiles" link="option=com_jce&view=browser">COM_JCE_MENU_FILEBROWSER</menu>
|
||||
</submenu>
|
||||
|
||||
<files folder="administrator/components/com_jce">
|
||||
<folder>controller</folder>
|
||||
<folder>helpers</folder>
|
||||
<folder>includes</folder>
|
||||
<folder>layouts</folder>
|
||||
<folder>models</folder>
|
||||
<folder>sql</folder>
|
||||
<folder>tables</folder>
|
||||
<folder>vendor</folder>
|
||||
<folder>views</folder>
|
||||
<file>access.xml</file>
|
||||
<file>config.xml</file>
|
||||
<file>controller.php</file>
|
||||
<file>index.html</file>
|
||||
<file>jce.php</file>
|
||||
<file>licence.txt</file>
|
||||
</files>
|
||||
|
||||
<languages folder="administrator/language/en-GB">
|
||||
<language tag="en-GB">en-GB.com_jce.ini</language>
|
||||
<language tag="en-GB">en-GB.com_jce.sys.ini</language>
|
||||
</languages>
|
||||
|
||||
</administration>
|
||||
</extension>
|
||||
22
administrator/components/com_jce/layouts/edit/additional.php
Normal file
22
administrator/components/com_jce/layouts/edit/additional.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
$plugins = $displayData->get('additional');
|
||||
|
||||
?>
|
||||
<fieldset class="<?php echo !empty($displayData->formclass) ? $displayData->formclass : ''; ?>">
|
||||
<legend><?php echo JText::_('WF_PROFILES_FEATURES_ADDITIONAL'); ?></legend>
|
||||
<div class="control-group">
|
||||
<div class="control-label"></div>
|
||||
<div class="controls">
|
||||
<div class="editor-features">
|
||||
<?php foreach ($plugins as $plugin): ?>
|
||||
<div class="control-group">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" value="<?php echo $plugin->name; ?>" <?php echo $plugin->active ? ' checked="checked"' : ''; ?>> <?php echo JText::_($plugin->title); ?>
|
||||
</label>
|
||||
<span class="help-block form-text text-muted w-100"><?php echo JText::_($plugin->description); ?></span>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
118
administrator/components/com_jce/layouts/edit/layout.php
Normal file
118
administrator/components/com_jce/layouts/edit/layout.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
$item = $displayData->get('Item');
|
||||
$form = $displayData->getForm();
|
||||
|
||||
$data = new JRegistry($form->getValue('config'));
|
||||
|
||||
$rows = $displayData->get('Rows');
|
||||
$plugins = $displayData->get('Plugins');
|
||||
$available = $displayData->get('AvailableButtons');
|
||||
|
||||
// width and height
|
||||
$width = $data->get('width', '100%');
|
||||
$height = $data->get('height', 'auto');
|
||||
|
||||
if (is_numeric($width) && strpos('%', $width) === false) {
|
||||
$width .= 'px';
|
||||
}
|
||||
if (is_numeric($height) && strpos('%', $height) === false) {
|
||||
$height .= 'px';
|
||||
}
|
||||
|
||||
?>
|
||||
<div class="control-group mt-3 mb-0 <?php echo !empty($displayData->formclass) ? $displayData->formclass : ''; ?>">
|
||||
<div class="control-label">
|
||||
<label class="hasPopover" title="<?php echo JText::_('WF_PROFILES_FEATURES_LAYOUT_EDITOR_DESC'); ?>"><?php echo JText::_('WF_PROFILES_FEATURES_LAYOUT_EDITOR'); ?></label>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<div class="editor-layout">
|
||||
<!-- Editor Toggle -->
|
||||
<span id="editor_toggle"><?php echo $data->get('toggle_label', '[Toggle Editor]'); ?></span>
|
||||
<!-- Width Marker -->
|
||||
<div class="widthMarker" style="width:<?php echo $width; ?>;">
|
||||
<span><?php echo $width; ?></span>
|
||||
</div>
|
||||
<!-- Toolbar -->
|
||||
<div class="mce-tinymce mce-container mce-panel mceEditor mceLayout mceDefaultSkin" role="application">
|
||||
<div class="mce-container-body mce-stack-layout mceLayout" style="max-width:<?php echo $width; ?>" role="presentation">
|
||||
<div class="mceToolbar sortableList" role="group">
|
||||
<?php foreach ($rows as $key => $groups) : ?>
|
||||
<div class="mce-container mce-toolbar mce-stack-layout-item mceToolbarRow mceToolbarRow<?php echo $key;?> Enabled sortableListItem">
|
||||
<?php foreach ($groups as $buttons) : ?>
|
||||
<!--div class="mce-container mce-flow-layout-item mce-btn-group" role="group"-->
|
||||
<?php foreach ($buttons as $button) : ?>
|
||||
<?php if (!empty($button->icon)) : ?>
|
||||
<div tabindex="-1" class="mceToolbarItem <?php echo $button->type; ?> mce-widget mce-btn" data-name="<?php echo $button->name; ?>" role="button" aria-label="<?php echo $button->title; ?>" aria-description="<?php echo $button->description; ?>">
|
||||
<?php foreach ($button->icon as $icon): ?>
|
||||
<div tabindex="-1" class="mceButton <?php echo $button->class; ?>" role="presentation" title="<?php echo $button->title; ?>">
|
||||
<?php if ($button->image) : ?>
|
||||
<span class="mceIcon mceIconImage"><img src="<?php echo $button->image; ?>" alt="" /></span>
|
||||
<?php else : ?>
|
||||
<span class="mce-ico mce-i-<?php echo $icon; ?> mceIcon mce_<?php echo $icon; ?>"></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
<!--/div-->
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<div class="mce-edit-area mce-container mce-panel mce-stack-layout-item mceIframeContainer">
|
||||
<div>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mce-statusbar mce-container mce-panel mce-last mce-stack-layout-item mceStatusbar mceLast">
|
||||
<div class="mce-container-body mce-flow-layout mcePathRow" role="group" tabindex="-1">
|
||||
<div class="mcePathLabel">Path: </div>
|
||||
<div aria-level="0" tabindex="-1" data-index="0" class="mce-path-item mce-last mcePathPath" role="button">p</div>
|
||||
</div>
|
||||
<div class="mce-flow-layout-item mce-last mce-resizehandle mceResize" tabindex="-1"></div>
|
||||
<div class="mce-wordcount mce-widget mce-label mce-flow-layout-item mceWordCount">Words: 69</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group mt-3 mb-4 <?php echo !empty($displayData->formclass) ? $displayData->formclass : ''; ?>">
|
||||
<div class="control-label">
|
||||
<label class="hasPopover" title="<?php echo JText::_('WF_PROFILES_FEATURES_LAYOUT_AVAILABLE_DESC'); ?>"><?php echo JText::_('WF_PROFILES_FEATURES_LAYOUT_AVAILABLE'); ?></label>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<div class="editor-button-pool">
|
||||
<div class="mce-tinymce mce-container mce-panel mceEditor mceLayout defaultSkin" role="application">
|
||||
<div class="mce-container-body mce-stack-layout mceLayout">
|
||||
<div class="mce-toolbar-grp mce-container mce-panel mce-stack-layout-item mceToolbar sortableList" role="toolbar">
|
||||
<?php for ($i = 0; $i < max(count($rows), 5); ++$i) : ?>
|
||||
<div class="mce-container mce-toolbar mce-stack-layout-item mceToolbarRow mceToolbarRow<?php echo $i;?> Enabled sortableListItem">
|
||||
<!--div class="mce-container mce-flow-layout-item mce-btn-group"-->
|
||||
<?php foreach ($available as $plugin) : ?>
|
||||
<?php if ($plugin->row && $plugin->row === $i): ?>
|
||||
<div tabindex="-1" class="mceToolbarItem <?php echo $plugin->type; ?> mce-widget mce-btn" data-name="<?php echo $plugin->name; ?>" role="button" aria-label="<?php echo $plugin->title; ?>" aria-description="<?php echo $plugin->description; ?>">
|
||||
<?php foreach ($plugin->icon as $icon): ?>
|
||||
<div tabindex="-1" class="mceButton <?php echo $plugin->class; ?>" role="presentation" title="<?php echo $plugin->title; ?>">
|
||||
<?php if ($plugin->image) : ?>
|
||||
<span class="mceIcon mceIconImage"><img src="<?php echo $plugin->image; ?>" alt="" /></span>
|
||||
<?php else : ?>
|
||||
<span class="mce-ico mce-i-<?php echo $icon; ?> mceIcon mce_<?php echo $icon; ?>"></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endforeach; ?>
|
||||
<!--/div-->
|
||||
</div>
|
||||
<?php endfor; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
69
administrator/components/com_jce/layouts/edit/plugins.php
Normal file
69
administrator/components/com_jce/layouts/edit/plugins.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?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
|
||||
*/
|
||||
$plugins = $displayData->get('Plugins');
|
||||
|
||||
?>
|
||||
<div class="form-horizontal tabbable tabs-left flex-column">
|
||||
<?php echo JHtml::_('bootstrap.startTabSet', 'plugins', array('active' => ''));
|
||||
foreach ($plugins as $plugin) {
|
||||
if (!$plugin->editable || empty($plugin->form)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$icons = '';
|
||||
$title = '';
|
||||
|
||||
$title .= '<p>' . $plugin->title . '</p>';
|
||||
|
||||
if (!empty($plugin->icon)) {
|
||||
|
||||
foreach ($plugin->icon as $icon) {
|
||||
$icons .= '<div class="mce-widget mce-btn mceButton ' . $plugin->class . '" title="' . $plugin->title . '"><span class="mce-ico mce-i-' . $icon . ' mceIcon mce_' . $icon . '"></span></div>';
|
||||
}
|
||||
|
||||
$title .= '<div class="mceEditor mceDefaultSkin"><div class="mce-container mce-toolbar mceToolBarItem">' . $icons . '</div></div>';
|
||||
}
|
||||
|
||||
echo JHtml::_('bootstrap.addTab', 'plugins', 'tabs-plugins-' . $plugin->name, $title); ?>
|
||||
<fieldset class="<?php echo !empty($displayData->formclass) ? $displayData->formclass : ''; ?>">
|
||||
<legend><?php echo $plugin->title; ?></legend>
|
||||
<div class="row-fluid">
|
||||
<hr />
|
||||
|
||||
<?php if ($plugin->form) :
|
||||
|
||||
echo $plugin->form->renderFieldset('config'); ?>
|
||||
|
||||
<hr />
|
||||
|
||||
<?php foreach ($plugin->extensions as $type => $extensions) : ?>
|
||||
<h3><?php echo JText::_('WF_EXTENSION_' . strtoupper($type), true); ?></h3>
|
||||
|
||||
<?php foreach ($extensions as $extension) : ?>
|
||||
|
||||
<div class="row-fluid">
|
||||
<h4><?php echo JText::_('PLG_JCE_' . strtoupper($type) . '_' . strtoupper($extension->name), true); ?></h4>
|
||||
<?php echo $extension->form->renderFieldset($type . '.' . $extension->name); ?>
|
||||
</div>
|
||||
|
||||
<?php endforeach; ?>
|
||||
|
||||
<hr />
|
||||
|
||||
<?php endforeach;
|
||||
|
||||
endif; ?>
|
||||
</div>
|
||||
</fieldset>
|
||||
<?php echo JHtml::_('bootstrap.endTab');
|
||||
}
|
||||
echo JHtml::_('bootstrap.endTabSet'); ?>
|
||||
</div>
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage Layout
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('JPATH_BASE') or die;
|
||||
|
||||
extract($displayData);
|
||||
|
||||
/**
|
||||
* Layout variables
|
||||
* -----------------
|
||||
* @var string $autocomplete Autocomplete attribute for the field.
|
||||
* @var boolean $autofocus Is autofocus enabled?
|
||||
* @var string $class Classes for the input.
|
||||
* @var string $description Description of the field.
|
||||
* @var boolean $disabled Is this field disabled?
|
||||
* @var string $group Group the field belongs to. <fields> section in form XML.
|
||||
* @var boolean $hidden Is this field hidden in the form?
|
||||
* @var string $hint Placeholder for the field.
|
||||
* @var string $id DOM id of the field.
|
||||
* @var string $label Label of the field.
|
||||
* @var string $labelclass Classes to apply to the label.
|
||||
* @var boolean $multiple Does this field support multiple values?
|
||||
* @var string $name Name of the input field.
|
||||
* @var string $onchange Onchange attribute for the field.
|
||||
* @var string $onclick Onclick attribute for the field.
|
||||
* @var string $pattern Pattern (Reg Ex) of value of the form field.
|
||||
* @var boolean $readonly Is this field read only?
|
||||
* @var boolean $repeat Allows extensions to duplicate elements.
|
||||
* @var boolean $required Is this field required?
|
||||
* @var integer $size Size attribute of the input.
|
||||
* @var boolean $spellcheck Spellcheck state for the form field.
|
||||
* @var string $validate Validation rules to apply.
|
||||
* @var string $value Value attribute of the field.
|
||||
* @var array $checkedOptions Options that will be set as checked.
|
||||
* @var boolean $hasValue Has this field a value assigned?
|
||||
* @var array $options Options available for this field.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The format of the input tag to be filled in using sprintf.
|
||||
* %1 - id
|
||||
* %2 - name
|
||||
* %3 - value
|
||||
* %4 = any other attributes
|
||||
*/
|
||||
$format = '<input type="checkbox" id="%1$s" value="%3$s" name="%2$s" %5$s /><label for="%1$s" class="checkbox blockformat-%3$s">%4$s</label>';
|
||||
|
||||
// The alt option for JText::alt
|
||||
$alt = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $name);
|
||||
?>
|
||||
|
||||
<fieldset id="<?php echo $id; ?>" class="<?php echo trim($class . ' checkboxes blockformats'); ?>">
|
||||
|
||||
<?php foreach ($options as $i => $option): ?>
|
||||
<?php
|
||||
// Initialize some option attributes.
|
||||
$checked = in_array((string) $option->value, $checkedOptions, true) ? 'checked' : '';
|
||||
|
||||
// In case there is no stored value, use the option's default state.
|
||||
$checked = (!$hasValue && $option->checked) ? 'checked' : $checked;
|
||||
$optionDisabled = !empty($option->disable) || $disabled ? 'disabled' : '';
|
||||
|
||||
$oid = $id . $i;
|
||||
$value = htmlspecialchars($option->value, ENT_COMPAT, 'UTF-8');
|
||||
$attributes = array_filter(array($checked, $optionDisabled));
|
||||
?>
|
||||
<div class="blockformat-item" title="<?php echo $option->text; ?>">
|
||||
<?php echo sprintf($format, $oid, $name, $value, $option->text, implode(' ', $attributes)); ?>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
|
||||
</fieldset>
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage Layout
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('JPATH_BASE') or die;
|
||||
|
||||
extract($displayData);
|
||||
|
||||
/**
|
||||
* Layout variables
|
||||
* -----------------
|
||||
* @var string $autocomplete Autocomplete attribute for the field.
|
||||
* @var boolean $autofocus Is autofocus enabled?
|
||||
* @var string $class Classes for the input.
|
||||
* @var string $description Description of the field.
|
||||
* @var boolean $disabled Is this field disabled?
|
||||
* @var string $group Group the field belongs to. <fields> section in form XML.
|
||||
* @var boolean $hidden Is this field hidden in the form?
|
||||
* @var string $hint Placeholder for the field.
|
||||
* @var string $id DOM id of the field.
|
||||
* @var string $label Label of the field.
|
||||
* @var string $labelclass Classes to apply to the label.
|
||||
* @var boolean $multiple Does this field support multiple values?
|
||||
* @var string $name Name of the input field.
|
||||
* @var string $onchange Onchange attribute for the field.
|
||||
* @var string $onclick Onclick attribute for the field.
|
||||
* @var string $pattern Pattern (Reg Ex) of value of the form field.
|
||||
* @var boolean $readonly Is this field read only?
|
||||
* @var boolean $repeat Allows extensions to duplicate elements.
|
||||
* @var boolean $required Is this field required?
|
||||
* @var integer $size Size attribute of the input.
|
||||
* @var boolean $spellcheck Spellcheck state for the form field.
|
||||
* @var string $validate Validation rules to apply.
|
||||
* @var string $value Value attribute of the field.
|
||||
* @var array $checkedOptions Options that will be set as checked.
|
||||
* @var boolean $hasValue Has this field a value assigned?
|
||||
* @var array $options Options available for this field.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The format of the input tag to be filled in using sprintf.
|
||||
* %1 - id
|
||||
* %2 - name
|
||||
* %3 - value
|
||||
* %4 = any other attributes
|
||||
*/
|
||||
$format = '<input type="checkbox" id="%1$s" name="%2$s" value="%3$s" %4$s />';
|
||||
|
||||
// The alt option for JText::alt
|
||||
$alt = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $name);
|
||||
?>
|
||||
|
||||
<fieldset id="<?php echo $id; ?>" class="<?php echo trim($class . ' checkboxes buttons'); ?>">
|
||||
|
||||
<?php foreach ($options as $i => $option) : ?>
|
||||
<?php
|
||||
// Initialize some option attributes.
|
||||
$checked = in_array((string) $option->value, $checkedOptions, true) ? 'checked' : '';
|
||||
|
||||
// In case there is no stored value, use the option's default state.
|
||||
$checked = (!$hasValue && $option->checked) ? 'checked' : $checked;
|
||||
$optionDisabled = !empty($option->disable) || $disabled ? 'disabled' : '';
|
||||
|
||||
$oid = $id . $i;
|
||||
$value = htmlspecialchars($option->value, ENT_COMPAT, 'UTF-8');
|
||||
$attributes = array_filter(array($checked, $optionDisabled));
|
||||
?>
|
||||
<div class="mce-widget mce-btn mceButton p-2" title="<?php echo $option->text;?>">
|
||||
<?php echo sprintf($format, $oid, $name, $value, implode(' ', $attributes)); ?>
|
||||
<span class="mce-ico mce-i-<?php echo $option->value;?> mceIcon mce_<?php echo $option->value;?>"></span>
|
||||
<label for="<?php echo $oid; ?>" class="checkbox"><?php echo $option->text; ?></label>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<input type="hidden" name="<?php echo $name;?>" value="" />
|
||||
</fieldset>
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage Layout
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
extract($displayData);
|
||||
|
||||
/**
|
||||
* Layout variables
|
||||
* -----------------
|
||||
* @var string $autocomplete Autocomplete attribute for the field.
|
||||
* @var boolean $autofocus Is autofocus enabled?
|
||||
* @var string $class Classes for the input.
|
||||
* @var string $description Description of the field.
|
||||
* @var boolean $disabled Is this field disabled?
|
||||
* @var string $group Group the field belongs to. <fields> section in form XML.
|
||||
* @var boolean $hidden Is this field hidden in the form?
|
||||
* @var string $hint Placeholder for the field.
|
||||
* @var string $id DOM id of the field.
|
||||
* @var string $label Label of the field.
|
||||
* @var string $labelclass Classes to apply to the label.
|
||||
* @var boolean $multiple Does this field support multiple values?
|
||||
* @var string $name Name of the input field.
|
||||
* @var string $onchange Onchange attribute for the field.
|
||||
* @var string $onclick Onclick attribute for the field.
|
||||
* @var string $pattern Pattern (Reg Ex) of value of the form field.
|
||||
* @var boolean $readonly Is this field read only?
|
||||
* @var boolean $repeat Allows extensions to duplicate elements.
|
||||
* @var boolean $required Is this field required?
|
||||
* @var integer $size Size attribute of the input.
|
||||
* @var boolean $spellcheck Spellcheck state for the form field.
|
||||
* @var string $validate Validation rules to apply.
|
||||
* @var string $value Value attribute of the field.
|
||||
* @var array $checkedOptions Options that will be set as checked.
|
||||
* @var boolean $hasValue Has this field a value assigned?
|
||||
* @var array $options Options available for this field.
|
||||
*/
|
||||
|
||||
// Including fallback code for HTML5 non supported browsers.
|
||||
JHtml::_('jquery.framework');
|
||||
JHtml::_('script', 'system/html5fallback.js', array('version' => 'auto', 'relative' => true, 'conditional' => 'lt IE 9'));
|
||||
|
||||
/**
|
||||
* The format of the input tag to be filled in using sprintf.
|
||||
* %1 - id
|
||||
* %2 - name
|
||||
* %3 - value
|
||||
* %4 = any other attributes
|
||||
*/
|
||||
$format = '<input type="checkbox" id="%1$s" name="%2$s" value="%3$s" %4$s />';
|
||||
|
||||
// The alt option for JText::alt
|
||||
$alt = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $name);
|
||||
?>
|
||||
|
||||
<fieldset id="<?php echo $id; ?>" class="<?php echo trim($class . ' checkboxes'); ?>"
|
||||
<?php echo $required ? 'required aria-required="true"' : ''; ?>
|
||||
<?php echo $autofocus ? 'autofocus' : ''; ?>>
|
||||
|
||||
<?php foreach ($options as $i => $option) : ?>
|
||||
<?php
|
||||
// Initialize some option attributes.
|
||||
$checked = in_array((string) $option->value, $checkedOptions, true) ? 'checked' : '';
|
||||
|
||||
// In case there is no stored value, use the option's default state.
|
||||
$checked = (!$hasValue && $option->checked) ? 'checked' : $checked;
|
||||
$optionClass = !empty($option->class) ? 'class="' . $option->class . '"' : '';
|
||||
$optionDisabled = !empty($option->disable) || $disabled ? 'disabled' : '';
|
||||
|
||||
// Initialize some JavaScript option attributes.
|
||||
$onclick = !empty($option->onclick) ? 'onclick="' . $option->onclick . '"' : '';
|
||||
$onchange = !empty($option->onchange) ? 'onchange="' . $option->onchange . '"' : '';
|
||||
|
||||
$oid = $id . $i;
|
||||
$value = htmlspecialchars($option->value, ENT_COMPAT, 'UTF-8');
|
||||
$attributes = array_filter(array($checked, $optionClass, $optionDisabled, $onchange, $onclick));
|
||||
?>
|
||||
|
||||
<label for="<?php echo $oid; ?>" class="checkbox">
|
||||
<?php echo sprintf($format, $oid, $name, $value, implode(' ', $attributes)); ?>
|
||||
<?php echo $option->text; ?></label>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<input type="hidden" name="<?php echo $name;?>" value="" />
|
||||
</fieldset>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage Layout
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('JPATH_BASE') or die;
|
||||
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
extract($displayData);
|
||||
|
||||
/**
|
||||
* Layout variables
|
||||
* -----------------
|
||||
* @var string $class Classes for the input.
|
||||
* @var string $id DOM id of the field.
|
||||
* @var string $name Name of the input field.
|
||||
* @var string $value Value attribute of the field.
|
||||
|
||||
*/
|
||||
|
||||
?>
|
||||
<div class="input-group input-append">
|
||||
<input type="text" class="colorpicker input-small" name="<?php echo $name; ?>" id="<?php echo $id; ?>" value="<?php echo htmlspecialchars($value, ENT_COMPAT, 'UTF-8'); ?>" placeholder="#rrggbb" />
|
||||
<div class="input-group-append">
|
||||
<span class="add-on input-group-text colorpicker_widget"></span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage Layout
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('JPATH_BASE') or die;
|
||||
|
||||
extract($displayData);
|
||||
|
||||
/**
|
||||
* Layout variables
|
||||
* -----------------
|
||||
* @var string $autocomplete Autocomplete attribute for the field.
|
||||
* @var boolean $autofocus Is autofocus enabled?
|
||||
* @var string $class Classes for the input.
|
||||
* @var string $description Description of the field.
|
||||
* @var boolean $disabled Is this field disabled?
|
||||
* @var string $group Group the field belongs to. <fields> section in form XML.
|
||||
* @var boolean $hidden Is this field hidden in the form?
|
||||
* @var string $hint Placeholder for the field.
|
||||
* @var string $id DOM id of the field.
|
||||
* @var string $label Label of the field.
|
||||
* @var string $labelclass Classes to apply to the label.
|
||||
* @var boolean $multiple Does this field support multiple values?
|
||||
* @var string $name Name of the input field.
|
||||
* @var string $onchange Onchange attribute for the field.
|
||||
* @var string $onclick Onclick attribute for the field.
|
||||
* @var string $pattern Pattern (Reg Ex) of value of the form field.
|
||||
* @var boolean $readonly Is this field read only?
|
||||
* @var boolean $repeat Allows extensions to duplicate elements.
|
||||
* @var boolean $required Is this field required?
|
||||
* @var integer $size Size attribute of the input.
|
||||
* @var boolean $spellcheck Spellcheck state for the form field.
|
||||
* @var string $validate Validation rules to apply.
|
||||
* @var string $value Value attribute of the field.
|
||||
* @var array $checkedOptions Options that will be set as checked.
|
||||
* @var boolean $hasValue Has this field a value assigned?
|
||||
* @var array $options Options available for this field.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The format of the input tag to be filled in using sprintf.
|
||||
* %1 - id
|
||||
* %2 - name
|
||||
* %3 - value
|
||||
* %4 = any other attributes
|
||||
*/
|
||||
$standard = '<input type="checkbox" id="%1$s" value="%3$s=%2$s" %4$s /><label for="%1$s" class="checkbox" style="font-family:%2$s">%3$s</label>';
|
||||
$custom = '<div class="span4 col-md-4"><input type="text" class="form-control span12" value="%3$s" placeholder="' . JText::_('WF_LABEL_NAME') . '" /></div><div class="span6 col-md-6"><input type="text" class="form-control span12" value="%2$s" placeholder="' . JText::_('WF_LABEL_FONTS') . ', eg: arial,helvetica,sans-serif" /></div><div class="span2 col-md-2"><a href="#" class="font-item-trash btn btn-link pull-right float-right"><i class="icon icon-trash"></i></a></div>';
|
||||
|
||||
// The alt option for JText::alt
|
||||
$alt = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $name);
|
||||
?>
|
||||
|
||||
<fieldset id="<?php echo $id; ?>" class="<?php echo trim($class . ' checkboxes fontlist'); ?>">
|
||||
|
||||
<?php foreach ($options as $i => $option): ?>
|
||||
<?php
|
||||
// Initialize some option attributes.
|
||||
$checked = $option->checked ? 'checked' : '';
|
||||
|
||||
$optionDisabled = !empty($option->disable) || $disabled ? 'disabled' : '';
|
||||
|
||||
$oid = $id . $i;
|
||||
$value = htmlspecialchars($option->value, ENT_COMPAT, 'UTF-8');
|
||||
$attributes = array_filter(array($checked, $optionDisabled));
|
||||
|
||||
$format = $standard;
|
||||
|
||||
if ($option->custom) {
|
||||
$format = $custom;
|
||||
}
|
||||
?>
|
||||
<div class="font-item row form-row" title="<?php echo $option->text; ?>">
|
||||
<?php echo sprintf($format, $oid, $value, $option->text, implode(' ', $attributes)); ?>
|
||||
</div>
|
||||
<?php endforeach;?>
|
||||
|
||||
<div class="font-item row form-row controls controls-row">
|
||||
<?php echo sprintf($custom, '', '', '', ''); ?>
|
||||
</div>
|
||||
|
||||
<div class="font-item row form-row" hidden>
|
||||
<?php echo sprintf($custom, '', '', '', ''); ?>
|
||||
</div>
|
||||
|
||||
<a href="#" class="btn btn-link font-item-plus"><span class="span10 col-md-10 text-left"><?php echo JText::_('WF_PARAM_FONTS_NEW');?></span><i class="icon icon-plus pull-right float-right"></i></a>
|
||||
|
||||
<input type="hidden" name="<?php echo $name;?>" value="" />
|
||||
|
||||
</fieldset>
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage Layout
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
?>
|
||||
|
||||
<fieldset class="<?php echo !empty($displayData->formclass) ? $displayData->formclass : 'form-horizontal'; ?>">
|
||||
<legend><?php echo $displayData->name; ?></legend>
|
||||
<?php if (!empty($displayData->description)) : ?>
|
||||
<p><?php echo $displayData->description; ?></p>
|
||||
<?php endif; ?>
|
||||
<?php $fieldsnames = explode(',', $displayData->fieldsname); ?>
|
||||
<?php foreach ($fieldsnames as $fieldname) : ?>
|
||||
<?php foreach ($displayData->form->getFieldset($fieldname) as $field) : ?>
|
||||
<?php $datashowon = ''; ?>
|
||||
<?php $groupClass = $field->type === 'Spacer' ? ' field-spacer' : ''; ?>
|
||||
<?php if ($field->showon) : ?>
|
||||
<?php JHtml::_('jquery.framework'); ?>
|
||||
<?php JHtml::_('script', 'jui/cms.js', array('version' => 'auto', 'relative' => true)); ?>
|
||||
<?php $datashowon = ' data-showon=\'' . json_encode(JFormHelper::parseShowOnConditions($field->showon, $field->formControl, $field->group)) . '\''; ?>
|
||||
<?php endif; ?>
|
||||
<div class="control-group<?php echo $groupClass; ?>"<?php echo $datashowon; ?>>
|
||||
<?php if (!isset($displayData->showlabel) || $displayData->showlabel) : ?>
|
||||
<div class="control-label"><?php echo $field->label; ?></div>
|
||||
<?php endif; ?>
|
||||
<div class="controls"><?php echo $field->input; ?></div>
|
||||
<?php if ($field->description) : ?>
|
||||
<small class="description"><?php echo JText::_($field->description); ?></small>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php endforeach; ?>
|
||||
</fieldset>
|
||||
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package JCE.System
|
||||
* @subpackage Layout
|
||||
*
|
||||
* @copyright (C) 2015 Open Source Matters, Inc. <https://www.joomla.org>
|
||||
* @copyright Copyright (C) 2022 Ryan Demmer All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('_JEXEC') or die;
|
||||
|
||||
use Joomla\CMS\Factory;
|
||||
use Joomla\CMS\Helper\MediaHelper;
|
||||
use Joomla\CMS\HTML\HTMLHelper;
|
||||
use Joomla\CMS\Language\Text;
|
||||
use Joomla\CMS\Router\Route;
|
||||
use Joomla\CMS\Uri\Uri;
|
||||
|
||||
extract($displayData);
|
||||
|
||||
/**
|
||||
* Layout variables
|
||||
* -----------------
|
||||
* @var string $asset The asset text
|
||||
* @var string $authorField The label text
|
||||
* @var integer $authorId The author id
|
||||
* @var string $class The class text
|
||||
* @var boolean $disabled True if field is disabled
|
||||
* @var string $folder The folder text
|
||||
* @var string $id The label text
|
||||
* @var string $link The link text
|
||||
* @var string $name The name text
|
||||
* @var string $preview The preview image relative path
|
||||
* @var integer $previewHeight The image preview height
|
||||
* @var integer $previewWidth The image preview width
|
||||
* @var string $onchange The onchange text
|
||||
* @var boolean $readonly True if field is readonly
|
||||
* @var integer $size The size text
|
||||
* @var string $value The value text
|
||||
* @var string $src The path and filename of the image
|
||||
* @var array $mediaTypes The supported media types for the Media Manager
|
||||
* @var array $imagesExt The supported extensions for images
|
||||
* @var array $audiosExt The supported extensions for audios
|
||||
* @var array $videosExt The supported extensions for videos
|
||||
* @var array $documentsExt The supported extensions for documents
|
||||
* @var string $dataAttribute Miscellaneous data attributes preprocessed for HTML output
|
||||
* @var array $dataAttributes Miscellaneous data attribute for eg, data-*
|
||||
*/
|
||||
|
||||
$attr = '';
|
||||
|
||||
// Initialize some field attributes.
|
||||
$attr .= !empty($class) ? ' class="form-control field-media-input ' . $class . '"' : ' class="form-control field-media-input"';
|
||||
$attr .= !empty($size) ? ' size="' . $size . '"' : '';
|
||||
$attr .= $dataAttribute;
|
||||
|
||||
// Initialize JavaScript field attributes.
|
||||
$attr .= !empty($onchange) ? ' onchange="' . $onchange . '"' : '';
|
||||
|
||||
switch ($preview) {
|
||||
case 'false':
|
||||
$showPreview = false;
|
||||
break;
|
||||
case 'true':
|
||||
default:
|
||||
$showPreview = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// clean up image src
|
||||
if (MediaHelper::isImage($value)) {
|
||||
$value = MediaHelper::getCleanMediaFieldValue($value);
|
||||
}
|
||||
|
||||
// Pre fill the contents of the popover
|
||||
if ($showPreview) {
|
||||
$cleanValue = MediaHelper::getCleanMediaFieldValue($value);
|
||||
|
||||
if ($cleanValue && file_exists(JPATH_ROOT . '/' . $cleanValue)) {
|
||||
$src = Uri::root() . $value;
|
||||
} else {
|
||||
$src = '';
|
||||
}
|
||||
|
||||
$width = $previewWidth;
|
||||
$height = $previewHeight;
|
||||
$style = '';
|
||||
$style .= ($width > 0) ? 'max-width:' . $width . 'px;' : '';
|
||||
$style .= ($height > 0) ? 'max-height:' . $height . 'px;' : '';
|
||||
|
||||
$imgattr = array(
|
||||
'id' => $id . '_preview',
|
||||
'class' => 'media-preview',
|
||||
'style' => $style,
|
||||
);
|
||||
|
||||
$img = HTMLHelper::_('image', $src, Text::_('JLIB_FORM_MEDIA_PREVIEW_ALT'), $imgattr);
|
||||
|
||||
$previewImg = '<div id="' . $id . '_preview_img">' . $img . '<span class="field-media-preview-icon"></span></div>';
|
||||
|
||||
$showPreview = 'static';
|
||||
}
|
||||
|
||||
// The url for the modal
|
||||
$url = $readonly ? '' : $link;
|
||||
|
||||
// Correctly route the url to ensure it's correctly using sef modes and subfolders
|
||||
$url = Route::_($url);
|
||||
$doc = Factory::getDocument();
|
||||
$wam = $doc->getWebAssetManager();
|
||||
|
||||
$modalHTML = HTMLHelper::_(
|
||||
'bootstrap.renderModal',
|
||||
'imageModal_' . $id,
|
||||
[
|
||||
'url' => $url,
|
||||
'title' => Text::_('JLIB_FORM_CHANGE_IMAGE'),
|
||||
'closeButton' => true,
|
||||
'height' => '100%',
|
||||
'width' => '100%',
|
||||
'modalWidth' => '80',
|
||||
'bodyHeight' => '60',
|
||||
'footer' => '<button type="button" class="btn btn-success button-save-selected">' . Text::_('JSELECT') . '</button>'
|
||||
. '<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">' . Text::_('JCANCEL') . '</button>',
|
||||
]
|
||||
);
|
||||
|
||||
// only load media field stylesheet
|
||||
$wam->useStyle('webcomponent.field-media');
|
||||
|
||||
?>
|
||||
<joomla-field-media class="field-media-wrapper wf-media-wrapper-custom"
|
||||
base-path="<?php echo Uri::root(); ?>"
|
||||
url="<?php echo $url; ?>"
|
||||
input=".field-media-input"
|
||||
button-select=".button-select"
|
||||
button-clear=".button-clear"
|
||||
button-save-selected=".button-save-selected" <?php /* button items remain in to prevent errors */ ?>
|
||||
>
|
||||
<?php echo $modalHTML; ?>
|
||||
<?php if ($showPreview) : ?>
|
||||
<div class="field-media-preview">
|
||||
<?php echo ' ' . $previewImg; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="input-group">
|
||||
<input type="text" name="<?php echo $name; ?>" id="<?php echo $id; ?>" value="<?php echo htmlspecialchars($value, ENT_COMPAT, 'UTF-8'); ?>" <?php echo $attr; ?>>
|
||||
<?php if ($disabled != true) : ?>
|
||||
<button type="button" class="btn btn-success button-select"><?php echo Text::_('JLIB_FORM_BUTTON_SELECT'); ?></button>
|
||||
<button type="button" class="btn btn-danger button-clear"><span class="icon-times" aria-hidden="true"></span><span class="visually-hidden"><?php echo Text::_('JLIB_FORM_BUTTON_CLEAR'); ?></span></button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</joomla-field-media>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage Layout
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
extract($displayData);
|
||||
|
||||
/**
|
||||
* Layout variables
|
||||
* ---------------------
|
||||
* $options : (array) Optional parameters
|
||||
* $label : (string) The html code for the label (not required if $options['hiddenLabel'] is true)
|
||||
* $input : (string) The input field html code
|
||||
*/
|
||||
|
||||
if (!empty($options['showonEnabled']))
|
||||
{
|
||||
JHtml::_('jquery.framework');
|
||||
JHtml::_('script', 'jui/cms.js', array('version' => 'auto', 'relative' => true));
|
||||
}
|
||||
|
||||
$class = empty($options['class']) ? '' : ' ' . $options['class'];
|
||||
$rel = empty($options['rel']) ? '' : ' ' . $options['rel'];
|
||||
?>
|
||||
<div class="control-group<?php echo $class; ?>"<?php echo $rel; ?>>
|
||||
<?php if (empty($options['hiddenLabel'])) : ?>
|
||||
<div class="control-label"><?php echo $label; ?></div>
|
||||
<?php endif; ?>
|
||||
<div class="controls"><?php echo $input; ?></div>
|
||||
<?php if (!empty($options['description'])) : ?>
|
||||
<small class="description"><?php echo JText::_($options['description']);?></small>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Site
|
||||
* @subpackage Layout
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
extract($displayData);
|
||||
|
||||
/**
|
||||
* Layout variables
|
||||
* ---------------------
|
||||
* $text : (string) The label text
|
||||
* $description : (string) An optional description to use in a tooltip
|
||||
* $for : (string) The id of the input this label is for
|
||||
* $required : (boolean) True if a required field
|
||||
* $classes : (array) A list of classes
|
||||
* $position : (string) The tooltip position. Bottom for alias
|
||||
*/
|
||||
|
||||
$classes = array_filter((array) $classes);
|
||||
|
||||
$id = $for . '-lbl';
|
||||
$title = '';
|
||||
|
||||
if (!empty($description))
|
||||
{
|
||||
if ($text && $text !== $description)
|
||||
{
|
||||
$classes[] = 'hasPopover';
|
||||
$title = ' title="' . htmlspecialchars(trim($text, ':')) . '"' . ' data-content="'. htmlspecialchars($description) . '"';
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
<label id="<?php echo $id; ?>" for="<?php echo $for; ?>"<?php if (!empty($classes)) echo ' class="' . implode(' ', $classes) . '"'; ?><?php echo $title; ?>>
|
||||
<?php echo $text; ?><?php if ($required) : ?><span class="star"> *</span><?php endif; ?>
|
||||
</label>
|
||||
12
administrator/components/com_jce/layouts/message/upgrade.php
Normal file
12
administrator/components/com_jce/layouts/message/upgrade.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<div class="alert alert-info" role="alert">
|
||||
<h4><i class="icon-star"></i> Go Pro and get more from JCE <a href="https://www.joomlacontenteditor.net/subscribe" class="btn btn-primary" target="_blank" title="Get JCE Editor Pro"><strong>Get JCE Editor Pro</strong></a></h4>
|
||||
<ul>
|
||||
<li>Resize, Thumbnail and Edit images</li>
|
||||
<li>Manage Audio and Video</li>
|
||||
<li>Create styled image captions</li>
|
||||
<li>Manage and create links to files</li>
|
||||
<li>Edit HTML in the Source Code Editor</li>
|
||||
<li>Write faster with <a href="https://en.wikipedia.org/wiki/Markdown" title="Markdown" target="_blank"><strong>Markdown</strong></a> support</li>
|
||||
<li>And much more...</li>
|
||||
</ul>
|
||||
</div>
|
||||
10
administrator/components/com_jce/layouts/message/welcome.php
Normal file
10
administrator/components/com_jce/layouts/message/welcome.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<div class="alert alert-info" role="alert">
|
||||
<h2>Welcome to JCE Pro!</h2>
|
||||
<p>You will now need to add the Pro buttons you require to the editor toolbar of each profile in use.</p>
|
||||
<ol>
|
||||
<li>Go to <a href="index.php?option=com_jce&view=profiles"><u>Editor Profiles</u></a> and click on the name a profile to edit it.</li>
|
||||
<li>Click on the Features & Layout tab, and scroll down to <strong>Current Editor Layout</strong></li>
|
||||
<li>Drag the buttons you require from the <strong>Available Buttons & Toolbars</strong> area into the <strong>Current Editor Layout</strong></li>
|
||||
<li>Click the <strong>Save</strong> button</li>
|
||||
</ol>
|
||||
</div>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?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;
|
||||
|
||||
$title = JText::_('WF_PROFILES_IMPORT_IMPORT');
|
||||
?>
|
||||
<joomla-toolbar-button>
|
||||
<div class="upload-profile-container">
|
||||
<input name="profile_file" accept="application/xml" type="file" />
|
||||
<button class="button-import btn btn-small btn-sm btn-outline-primary"><span class="icon-upload text-body" title="<?php echo $title; ?>"></span> <?php echo $title; ?></button>
|
||||
</div>
|
||||
</joomla-toolbar-button>
|
||||
339
administrator/components/com_jce/licence.txt
Normal file
339
administrator/components/com_jce/licence.txt
Normal file
@@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
39
administrator/components/com_jce/models/browser.php
Normal file
39
administrator/components/com_jce/models/browser.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?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/helpers/browser.php';
|
||||
|
||||
class JceModelBrowser extends JModelLegacy
|
||||
{
|
||||
/**
|
||||
* Method to auto-populate the model state.
|
||||
*
|
||||
* Note. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function populateState($ordering = null, $direction = null)
|
||||
{
|
||||
$app = JFactory::getApplication();
|
||||
|
||||
$filter = $app->input->getCmd('filter', '');
|
||||
|
||||
$url = WfBrowserHelper::getBrowserLink(null, $filter);
|
||||
|
||||
if (empty($url)) {
|
||||
$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');
|
||||
$app->redirect('index.php?option=com_jce');
|
||||
}
|
||||
|
||||
$this->setState('url', $url);
|
||||
}
|
||||
}
|
||||
214
administrator/components/com_jce/models/config.php
Normal file
214
administrator/components/com_jce/models/config.php
Normal file
@@ -0,0 +1,214 @@
|
||||
<?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;
|
||||
|
||||
// load base model
|
||||
jimport('joomla.application.component.modelform');
|
||||
|
||||
class JceModelConfig extends JModelForm
|
||||
{
|
||||
/**
|
||||
* Returns a Table object, always creating it.
|
||||
*
|
||||
* @param type $type The table type to instantiate
|
||||
* @param string $prefix A prefix for the table class name. Optional
|
||||
* @param array $config Configuration array for model. Optional
|
||||
*
|
||||
* @return JTable A database object
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function getTable($type = 'Extension', $prefix = 'JTable', $config = array())
|
||||
{
|
||||
return JTable::getInstance($type, $prefix, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a form object.
|
||||
*
|
||||
* @param array $data Data for the form
|
||||
* @param bool $loadData True if the form is to load its own data (default case), false if not
|
||||
*
|
||||
* @return mixed A JForm object on success, false on failure
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function getForm($data = array(), $loadData = true)
|
||||
{
|
||||
// Get the form.
|
||||
$form = $this->loadForm('com_jce.config', 'config', array('control' => 'jform', 'load_data' => $loadData));
|
||||
|
||||
if (empty($form)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the data that should be injected in the form.
|
||||
*
|
||||
* @return mixed The data for the form
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function loadFormData()
|
||||
{
|
||||
// Check the session for previously entered form data.
|
||||
$data = JFactory::getApplication()->getUserState('com_jce.config.data', array());
|
||||
|
||||
if (empty($data)) {
|
||||
$data = $this->getData();
|
||||
}
|
||||
|
||||
$this->preprocessData('com_jce.config', $data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/* Override to prevent plugins from processing form data */
|
||||
protected function preprocessData($context, &$data, $group = 'system')
|
||||
{
|
||||
if (!isset($data->params)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$config = $data->params;
|
||||
|
||||
if (is_string($config)) {
|
||||
$config = json_decode($config, true);
|
||||
}
|
||||
|
||||
if (empty($config)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($config['custom_config'])) {
|
||||
// settings syntax, eg: key:value
|
||||
if (is_string($config['custom_config']) && strpos($config['custom_config'], ':') !== false) {
|
||||
|
||||
if (!WFUtility::isJson($config['custom_config'])) {
|
||||
$values = explode(';', $config['custom_config']);
|
||||
|
||||
// reset as array
|
||||
$config['custom_config'] = array();
|
||||
|
||||
foreach ($values as $value) {
|
||||
list($key, $val) = explode(':', $value);
|
||||
|
||||
$config['custom_config'][] = array(
|
||||
'name' => $key,
|
||||
'value' => trim($val, " \t\n\r\0\x0B'\""),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$data->params = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the configuration data.
|
||||
*
|
||||
* This method will load the global configuration data straight from
|
||||
* JConfig. If configuration data has been saved in the session, that
|
||||
* data will be merged into the original data, overwriting it.
|
||||
*
|
||||
* @return array An array containg all global config data
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
$table = $this->getTable();
|
||||
|
||||
$id = $table->find(array(
|
||||
'type' => 'plugin',
|
||||
'element' => 'jce',
|
||||
'folder' => 'editors',
|
||||
));
|
||||
|
||||
if (!$table->load($id)) {
|
||||
$this->setError($table->getError());
|
||||
return false;
|
||||
}
|
||||
|
||||
// json_decode
|
||||
$json = json_decode($table->params, true);
|
||||
|
||||
if (empty($json)) {
|
||||
$json = array();
|
||||
}
|
||||
|
||||
array_walk($json, function (&$value, $key) {
|
||||
if (is_numeric($value)) {
|
||||
$value = $value + 0;
|
||||
}
|
||||
});
|
||||
|
||||
$data = new StdClass;
|
||||
$data->params = $json;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to save the form data.
|
||||
*
|
||||
* @param array The form data
|
||||
*
|
||||
* @return bool True on success
|
||||
*
|
||||
* @since 2.7
|
||||
*/
|
||||
public function save($data)
|
||||
{
|
||||
$table = $this->getTable();
|
||||
|
||||
$id = $table->find(array(
|
||||
'type' => 'plugin',
|
||||
'element' => 'jce',
|
||||
'folder' => 'editors',
|
||||
));
|
||||
|
||||
if (!$id) {
|
||||
$this->setError('Invalid plugin');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the previous Data
|
||||
if (!$table->load($id)) {
|
||||
$this->setError($table->getError());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bind the data.
|
||||
if (!$table->bind($data)) {
|
||||
$this->setError($table->getError());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the data.
|
||||
if (!$table->check()) {
|
||||
$this->setError($table->getError());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store the data.
|
||||
if (!$table->store()) {
|
||||
$this->setError($table->getError());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
128
administrator/components/com_jce/models/cpanel.php
Normal file
128
administrator/components/com_jce/models/cpanel.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?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/constants.php';
|
||||
|
||||
class JceModelCpanel extends JModelLegacy
|
||||
{
|
||||
public function getIcons()
|
||||
{
|
||||
$user = JFactory::getUser();
|
||||
|
||||
$icons = array();
|
||||
|
||||
$views = array(
|
||||
'config' => 'equalizer',
|
||||
'profiles' => 'users',
|
||||
'browser' => 'picture',
|
||||
'mediabox' => 'pictures',
|
||||
);
|
||||
|
||||
foreach ($views as $name => $icon) {
|
||||
|
||||
// if its mediabox, check the plugin is installed and enabled
|
||||
if ($name === "mediabox" && !JPluginHelper::isEnabled('system', 'jcemediabox')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if its allowed...
|
||||
if (!$user->authorise('jce.' . $name, 'com_jce')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$link = 'index.php?option=com_jce&view=' . $name;
|
||||
$title = JText::_('WF_' . strtoupper($name));
|
||||
|
||||
if ($name === "browser") {
|
||||
if (!JPluginHelper::isEnabled('quickicon', 'jce')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$title = JText::_('WF_' . strtoupper($name) . '_TITLE');
|
||||
}
|
||||
|
||||
$icons[] = '<li class="quickicon mb-3"><a title="' . JText::_('WF_' . strtoupper($name) . '_DESC') . '" href="' . $link . '" class="btn btn-default" role="button"><div class="quickicon-icon d-flex align-items-end" role="presentation"><span class="fa fa-' . $icon . ' icon-' . $icon . '" aria-hidden="true" role="presentation"></span></div><div class="quickicon-text d-flex align-items-center"><span class="j-links-link">' . $title . '</span></div></a></li>';
|
||||
}
|
||||
|
||||
return $icons;
|
||||
}
|
||||
|
||||
public function getFeeds()
|
||||
{
|
||||
$app = JFactory::getApplication();
|
||||
$params = JComponentHelper::getParams('com_jce');
|
||||
$limit = $params->get('feed_limit', 2);
|
||||
|
||||
$feeds = array();
|
||||
$options = array(
|
||||
'rssUrl' => 'https://www.joomlacontenteditor.net/news?format=feed',
|
||||
);
|
||||
|
||||
$xml = simplexml_load_file($options['rssUrl']);
|
||||
|
||||
if (empty($xml)) {
|
||||
return $feeds;
|
||||
}
|
||||
|
||||
jimport('joomla.filter.input');
|
||||
$filter = JFilterInput::getInstance();
|
||||
|
||||
$count = count($xml->channel->item);
|
||||
|
||||
if ($count) {
|
||||
$count = ($count > $limit) ? $limit : $count;
|
||||
|
||||
for ($i = 0; $i < $count; ++$i) {
|
||||
$feed = new StdClass();
|
||||
$item = $xml->channel->item[$i];
|
||||
|
||||
$link = (string) $item->link;
|
||||
$feed->link = htmlspecialchars($filter->clean($link));
|
||||
|
||||
$title = (string) $item->title;
|
||||
$feed->title = htmlspecialchars($filter->clean($title));
|
||||
|
||||
$description = (string) $item->description;
|
||||
$feed->description = htmlspecialchars($filter->clean($description));
|
||||
|
||||
$feeds[] = $feed;
|
||||
}
|
||||
}
|
||||
|
||||
return $feeds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state.
|
||||
*
|
||||
* Note. Calling getState in this method will result in recursion.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function populateState($ordering = null, $direction = null)
|
||||
{
|
||||
$licence = "";
|
||||
$version = "";
|
||||
|
||||
if ($xml = simplexml_load_file(JPATH_ADMINISTRATOR . '/components/com_jce/jce.xml')) {
|
||||
$licence = (string) $xml->license;
|
||||
$version = (string) $xml->version;
|
||||
|
||||
if (WF_EDITOR_PRO) {
|
||||
$version = '<span class="badge badge-info badge-primary bg-primary">Pro</span> ' . $version;
|
||||
}
|
||||
}
|
||||
|
||||
$this->setState('version', $version);
|
||||
$this->setState('licence', $licence);
|
||||
}
|
||||
}
|
||||
63
administrator/components/com_jce/models/editor.php
Normal file
63
administrator/components/com_jce/models/editor.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?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 WFModelEditor extends JObject
|
||||
{
|
||||
private static $editor;
|
||||
|
||||
public function buildEditor()
|
||||
{
|
||||
if (!isset(self::$editor)) {
|
||||
self::$editor = new WFEditor();
|
||||
}
|
||||
|
||||
$settings = self::$editor->getEditorSettings();
|
||||
|
||||
return self::$editor->render($settings);
|
||||
}
|
||||
|
||||
public function getEditorSettings()
|
||||
{
|
||||
if (!isset(self::$editor)) {
|
||||
self::$editor = new WFEditor();
|
||||
}
|
||||
|
||||
return self::$editor->getEditorSettings();
|
||||
}
|
||||
|
||||
public function render($settings = array())
|
||||
{
|
||||
if (!isset(self::$editor)) {
|
||||
self::$editor = new WFEditor();
|
||||
}
|
||||
|
||||
if (empty($settings)) {
|
||||
$settings = self::$editor->getEditorSettings();
|
||||
}
|
||||
|
||||
self::$editor->render($settings);
|
||||
|
||||
$document = JFactory::getDocument();
|
||||
|
||||
foreach (self::$editor->getScripts() as $script) {
|
||||
$document->addScript($script, array('version' => 'auto'), array('defer' => 'defer'));
|
||||
}
|
||||
|
||||
foreach (self::$editor->getStyleSheets() as $style) {
|
||||
$document->addStylesheet($style, array('version' => 'auto'));
|
||||
}
|
||||
|
||||
$script = "document.addEventListener('DOMContentLoaded',function handler(){" . implode("", self::$editor->getScriptDeclaration()) . ";this.removeEventListener('DOMContentLoaded',handler);});";
|
||||
|
||||
$document->addScriptDeclaration($script);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
class JFormFieldBlockformats extends JFormFieldCheckboxes
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $type = 'Blockformats';
|
||||
|
||||
/**
|
||||
* Name of the layout being used to render the field
|
||||
*
|
||||
* @var string
|
||||
* @since 3.5
|
||||
*/
|
||||
protected $layout = 'form.field.blockformats';
|
||||
|
||||
protected static $blockformats = array(
|
||||
'p' => 'Paragraph',
|
||||
'div' => 'Div',
|
||||
'div_container' => 'Div Container',
|
||||
'h1' => 'Heading1',
|
||||
'h2' => 'Heading2',
|
||||
'h3' => 'Heading3',
|
||||
'h4' => 'Heading4',
|
||||
'h5' => 'Heading5',
|
||||
'h6' => 'Heading6',
|
||||
'blockquote' => 'Blockquote',
|
||||
'address' => 'Address',
|
||||
'code' => 'Code',
|
||||
'pre' => 'Preformatted',
|
||||
'samp' => 'Sample',
|
||||
'span' => 'Span',
|
||||
'section' => 'Section',
|
||||
'article' => 'Article',
|
||||
'aside' => 'Aside',
|
||||
'header' => 'Header',
|
||||
'footer' => 'Footer',
|
||||
'nav' => 'Nav',
|
||||
'figure' => 'Figure',
|
||||
'dt' => 'Definition Term',
|
||||
'dd' => 'Definition List'
|
||||
);
|
||||
|
||||
/**
|
||||
* Allow to override renderer include paths in child fields
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
protected function getLayoutPaths()
|
||||
{
|
||||
return array(JPATH_ADMINISTRATOR . '/components/com_jce/layouts', JPATH_SITE . '/layouts');
|
||||
}
|
||||
|
||||
protected function getOptions()
|
||||
{
|
||||
$fieldname = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname);
|
||||
$options = array();
|
||||
|
||||
if (empty($this->value)) {
|
||||
$data = array_keys(self::$blockformats);
|
||||
$values = $data;
|
||||
} else {
|
||||
if (is_string($this->value)) {
|
||||
$this->value = explode(',', $this->value);
|
||||
}
|
||||
$values = $this->value;
|
||||
$data = array_unique(array_merge($this->value, array_keys(self::$blockformats)));
|
||||
}
|
||||
|
||||
// create default font structure
|
||||
foreach ($data as $format) {
|
||||
if (array_key_exists($format, self::$blockformats) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$text = self::$blockformats[$format];
|
||||
|
||||
$tmp = array(
|
||||
'value' => $format,
|
||||
'text' => JText::alt($text, $fieldname),
|
||||
'checked' => in_array($format, $values)
|
||||
);
|
||||
|
||||
$options[] = (object) $tmp;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
73
administrator/components/com_jce/models/fields/buttons.php
Normal file
73
administrator/components/com_jce/models/fields/buttons.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
JFormHelper::loadFieldClass('checkboxes');
|
||||
|
||||
class JFormFieldButtons extends JFormFieldCheckboxes
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $type = 'Buttons';
|
||||
|
||||
/**
|
||||
* Name of the layout being used to render the field
|
||||
*
|
||||
* @var string
|
||||
* @since 3.5
|
||||
*/
|
||||
protected $layout = 'form.field.buttons';
|
||||
|
||||
/**
|
||||
* Method to get the field label markup for a spacer.
|
||||
* Use the label text or name from the XML element as the spacer or
|
||||
* Use a hr="true" to automatically generate plain hr markup.
|
||||
*
|
||||
* @return string The field label markup
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function getLabel()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to attach a JForm object to the field.
|
||||
*
|
||||
* @param SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object
|
||||
* @param mixed $value The form field value to validate
|
||||
* @param string $group The field name group control value. This acts as as an array container for the field.
|
||||
* For example if the field has name="foo" and the group value is set to "bar" then the
|
||||
* full field name would end up being "bar[foo]"
|
||||
*
|
||||
* @return bool True on success
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function setup(SimpleXMLElement $element, $value, $group = null)
|
||||
{
|
||||
$return = parent::setup($element, $value, $group);
|
||||
|
||||
$this->class = trim($this->class . ' mceDefaultSkin');
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow to override renderer include paths in child fields
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
protected function getLayoutPaths()
|
||||
{
|
||||
return array(JPATH_ADMINISTRATOR . '/components/com_jce/layouts', JPATH_SITE . '/layouts');
|
||||
}
|
||||
}
|
||||
180
administrator/components/com_jce/models/fields/checkboxes.php
Normal file
180
administrator/components/com_jce/models/fields/checkboxes.php
Normal file
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Form
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2020 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
JFormHelper::loadFieldClass('list');
|
||||
|
||||
/**
|
||||
* Form Field class for the Joomla Platform.
|
||||
* Displays options as a list of checkboxes.
|
||||
* Multiselect may be forced to be true.
|
||||
*
|
||||
* @see JFormFieldCheckbox
|
||||
* @since 1.7.0
|
||||
*/
|
||||
class JFormFieldCheckboxes extends JFormFieldList
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
* @since 1.7.0
|
||||
*/
|
||||
protected $type = 'Checkboxes';
|
||||
|
||||
/**
|
||||
* Name of the layout being used to render the field
|
||||
*
|
||||
* @var string
|
||||
* @since 3.5
|
||||
*/
|
||||
protected $layout = 'form.field.checkboxes';
|
||||
|
||||
/**
|
||||
* Flag to tell the field to always be in multiple values mode.
|
||||
*
|
||||
* @var boolean
|
||||
* @since 1.7.0
|
||||
*/
|
||||
protected $forceMultiple = true;
|
||||
|
||||
/**
|
||||
* The comma separated list of checked checkboxes value.
|
||||
*
|
||||
* @var mixed
|
||||
* @since 3.2
|
||||
*/
|
||||
public $checkedOptions;
|
||||
|
||||
/**
|
||||
* Method to get certain otherwise inaccessible properties from the form field object.
|
||||
*
|
||||
* @param string $name The property name for which to get the value.
|
||||
*
|
||||
* @return mixed The property value or null.
|
||||
*
|
||||
* @since 3.2
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
switch ($name)
|
||||
{
|
||||
case 'forceMultiple':
|
||||
case 'checkedOptions':
|
||||
return $this->$name;
|
||||
}
|
||||
|
||||
return parent::__get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to set certain otherwise inaccessible properties of the form field object.
|
||||
*
|
||||
* @param string $name The property name for which to set the value.
|
||||
* @param mixed $value The value of the property.
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @since 3.2
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
switch ($name)
|
||||
{
|
||||
case 'checkedOptions':
|
||||
$this->checkedOptions = (string) $value;
|
||||
break;
|
||||
|
||||
default:
|
||||
parent::__set($name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the radio button field input markup.
|
||||
*
|
||||
* @return string The field input markup.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
protected function getInput()
|
||||
{
|
||||
if (empty($this->layout))
|
||||
{
|
||||
throw new UnexpectedValueException(sprintf('%s has no layout assigned.', $this->name));
|
||||
}
|
||||
|
||||
return $this->getRenderer($this->layout)->render($this->getLayoutData());
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to attach a JForm object to the field.
|
||||
*
|
||||
* @param SimpleXMLElement $element The SimpleXMLElement object representing the `<field>` tag for the form field object.
|
||||
* @param mixed $value The form field value to validate.
|
||||
* @param string $group The field name group control value. This acts as an array container for the field.
|
||||
* For example if the field has name="foo" and the group value is set to "bar" then the
|
||||
* full field name would end up being "bar[foo]".
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @see JFormField::setup()
|
||||
* @since 3.2
|
||||
*/
|
||||
public function setup(SimpleXMLElement $element, $value, $group = null)
|
||||
{
|
||||
$return = parent::setup($element, $value, $group);
|
||||
|
||||
if ($return)
|
||||
{
|
||||
$this->checkedOptions = (string) $this->element['checked'];
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the data to be passed to the layout for rendering.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
protected function getLayoutData()
|
||||
{
|
||||
$data = parent::getLayoutData();
|
||||
|
||||
// True if the field has 'value' set. In other words, it has been stored, don't use the default values.
|
||||
$hasValue = (isset($this->value) && !empty($this->value));
|
||||
|
||||
// If a value has been stored, use it. Otherwise, use the defaults.
|
||||
$checkedOptions = $hasValue ? $this->value : $this->checkedOptions;
|
||||
|
||||
$extraData = array(
|
||||
'checkedOptions' => is_array($checkedOptions) ? $checkedOptions : explode(',', (string) $checkedOptions),
|
||||
'hasValue' => $hasValue,
|
||||
'options' => $this->getOptions(),
|
||||
);
|
||||
|
||||
return array_merge($data, $extraData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow to override renderer include paths in child fields
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
protected function getLayoutPaths()
|
||||
{
|
||||
return array(JPATH_ADMINISTRATOR . '/components/com_jce/layouts', JPATH_SITE . '/layouts');
|
||||
}
|
||||
}
|
||||
50
administrator/components/com_jce/models/fields/color.php
Normal file
50
administrator/components/com_jce/models/fields/color.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* @package Joomla.Platform
|
||||
* @subpackage Form
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2018 Open Source Matters, Inc. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
JFormHelper::loadFieldClass('color');
|
||||
|
||||
/**
|
||||
* Color Form Field class for the Joomla Platform.
|
||||
* This implementation is designed to be compatible with HTML5's `<input type="color">`
|
||||
*
|
||||
* @link http://www.w3.org/TR/html-markup/input.color.html
|
||||
* @since 11.3
|
||||
*/
|
||||
class JFormFieldColorPicker extends JFormFieldColor
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
* @since 11.3
|
||||
*/
|
||||
protected $type = 'ColorPicker';
|
||||
|
||||
/**
|
||||
* Name of the layout being used to render the field
|
||||
*
|
||||
* @var string
|
||||
* @since 3.5
|
||||
*/
|
||||
protected $layout = 'form.field.colorpicker';
|
||||
|
||||
/**
|
||||
* Allow to override renderer include paths in child fields
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
protected function getLayoutPaths()
|
||||
{
|
||||
return array(JPATH_ADMINISTRATOR . '/components/com_jce/layouts', JPATH_SITE . '/layouts');
|
||||
}
|
||||
}
|
||||
101
administrator/components/com_jce/models/fields/components.php
Normal file
101
administrator/components/com_jce/models/fields/components.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
JFormHelper::loadFieldClass('list');
|
||||
|
||||
/**
|
||||
* Form Field class for the Joomla Framework.
|
||||
*
|
||||
* @since 11.4
|
||||
*/
|
||||
class JFormFieldComponents extends JFormFieldList
|
||||
{
|
||||
/**
|
||||
* The field type.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 11.4
|
||||
*/
|
||||
protected $type = 'Components';
|
||||
|
||||
/**
|
||||
* Method to get a list of options for a list input.
|
||||
*
|
||||
* @return array An array of JHtml options
|
||||
*
|
||||
* @since 11.4
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
$language = JFactory::getLanguage();
|
||||
|
||||
$exclude = array(
|
||||
'com_admin',
|
||||
'com_cache',
|
||||
'com_checkin',
|
||||
'com_config',
|
||||
'com_cpanel',
|
||||
'com_fields',
|
||||
'com_finder',
|
||||
'com_installer',
|
||||
'com_languages',
|
||||
'com_login',
|
||||
'com_mailto',
|
||||
'com_menus',
|
||||
'com_media',
|
||||
'com_messages',
|
||||
'com_newsfeeds',
|
||||
'com_plugins',
|
||||
'com_redirect',
|
||||
'com_templates',
|
||||
'com_users',
|
||||
'com_wrapper',
|
||||
'com_search',
|
||||
'com_user',
|
||||
'com_updates',
|
||||
);
|
||||
|
||||
// Get list of plugins
|
||||
$db = JFactory::getDbo();
|
||||
$query = $db->getQuery(true)
|
||||
->select('element AS value, name AS text')
|
||||
->from('#__extensions')
|
||||
->where('type = '.$db->quote('component'))
|
||||
->where('enabled = 1')
|
||||
->order('ordering, name');
|
||||
$db->setQuery($query);
|
||||
|
||||
$components = $db->loadObjectList();
|
||||
|
||||
$options = array();
|
||||
|
||||
// load component languages
|
||||
for ($i = 0; $i < count($components); ++$i) {
|
||||
if (!in_array($components[$i]->value, $exclude)) {
|
||||
// load system language file
|
||||
$language->load($components[$i]->value.'.sys', JPATH_ADMINISTRATOR);
|
||||
$language->load($components[$i]->value, JPATH_ADMINISTRATOR);
|
||||
|
||||
if ($components[$i]->text === "COM_JCE") {
|
||||
$components[$i]->text = "WF_CPANEL_BROWSER";
|
||||
}
|
||||
|
||||
// translate name
|
||||
$components[$i]->text = JText::_($components[$i]->text, true);
|
||||
|
||||
$components[$i]->disable = '';
|
||||
|
||||
$options[] = $components[$i];
|
||||
}
|
||||
}
|
||||
|
||||
// Merge any additional options in the XML definition.
|
||||
return array_merge(parent::getOptions(), $options);
|
||||
}
|
||||
}
|
||||
114
administrator/components/com_jce/models/fields/container.php
Normal file
114
administrator/components/com_jce/models/fields/container.php
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
/**
|
||||
* @package JCE
|
||||
* @subpackage Component
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2019 Open Source Matters, Inc. All rights reserved.
|
||||
* @copyright Copyright (C) 2006 - 2020 Ryan Demmer. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* Form Field class for the JCE.
|
||||
* Display a field with a repeatable set of defined sub fields
|
||||
*
|
||||
* @since 2.8.13
|
||||
*/
|
||||
class JFormFieldContainer extends JFormField
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.8.13
|
||||
*/
|
||||
protected $type = 'Container';
|
||||
|
||||
/**
|
||||
* Method to get the field label markup for a spacer.
|
||||
* Use the label text or name from the XML element as the spacer or
|
||||
* Use a hr="true" to automatically generate plain hr markup.
|
||||
*
|
||||
* @return string The field label markup
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function getLabel()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the field input markup.
|
||||
*
|
||||
* @return string The field input markup.
|
||||
*
|
||||
* @since 2.8.13
|
||||
*/
|
||||
protected function getInput()
|
||||
{
|
||||
$group = $this->group;
|
||||
|
||||
// subfields require JCE Pro
|
||||
if (isset($this->element['pro']) && !WF_EDITOR_PRO) {
|
||||
return "";
|
||||
}
|
||||
|
||||
$subForm = new JForm('', array('control' => $this->formControl . '[' . str_replace('.', '][', $group) . ']'));
|
||||
$children = $this->element->children();
|
||||
|
||||
$subForm->load($children);
|
||||
$subForm->setFields($children);
|
||||
|
||||
$data = $this->form->getData()->toObject();
|
||||
|
||||
// extract relevant data level using group
|
||||
foreach (explode('.', $group) as $key) {
|
||||
if (isset($data->$key)) {
|
||||
$data = $data->$key;
|
||||
}
|
||||
}
|
||||
|
||||
$subForm->bind($data);
|
||||
|
||||
// And finaly build a main container
|
||||
$str = array();
|
||||
|
||||
$fields = $subForm->getFieldset();
|
||||
|
||||
if ($this->class === 'inset') {
|
||||
$this->class .= ' well well-small well-light p-4 bg-light';
|
||||
}
|
||||
|
||||
$str[] = '<div class="form-field-container ' . $this->class . '">';
|
||||
$str[] = ' <fieldset class="form-field-container-group">';
|
||||
|
||||
if ($this->element['label']) {
|
||||
$text = $this->element['label'];
|
||||
$text = $this->translateLabel ? JText::_($text) : $text;
|
||||
|
||||
$str[] = '<legend>' . $text . '</legend>';
|
||||
}
|
||||
|
||||
if ($this->element['description']) {
|
||||
$text = $this->element['description'];
|
||||
$text = $this->translateLabel ? JText::_($text) : $text;
|
||||
|
||||
$str[] = '<small class="description">' . $text . '</small>';
|
||||
|
||||
// reset description
|
||||
$this->description = '';
|
||||
}
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$str[] = $field->renderField(array('description' => $field->description));
|
||||
}
|
||||
|
||||
$str[] = ' </fieldset>';
|
||||
$str[] = '</div>';
|
||||
|
||||
return implode("", $str);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
JFormHelper::loadFieldClass('list');
|
||||
|
||||
class JFormFieldCustomList extends JFormFieldList
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $type = 'CustomList';
|
||||
|
||||
/**
|
||||
* Method to attach a JForm object to the field.
|
||||
*
|
||||
* @param SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object
|
||||
* @param mixed $value The form field value to validate
|
||||
* @param string $group The field name group control value. This acts as as an array container for the field.
|
||||
* For example if the field has name="foo" and the group value is set to "bar" then the
|
||||
* full field name would end up being "bar[foo]"
|
||||
*
|
||||
* @return bool True on success
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function setup(SimpleXMLElement $element, $value, $group = null)
|
||||
{
|
||||
$return = parent::setup($element, $value, $group);
|
||||
|
||||
$this->class = trim($this->class.' com_jce_select_custom');
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
protected function getOptions()
|
||||
{
|
||||
$options = parent::getOptions();
|
||||
|
||||
$this->value = is_array($this->value) ? $this->value : explode(',', $this->value);
|
||||
|
||||
$custom = array();
|
||||
|
||||
foreach ($this->value as $value) {
|
||||
$tmp = array(
|
||||
'value' => $value,
|
||||
'text' => $value,
|
||||
'selected' => true,
|
||||
);
|
||||
|
||||
$found = false;
|
||||
|
||||
foreach($options as $option) {
|
||||
if ($option->value === $value) {
|
||||
$found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found) {
|
||||
$custom[] = (object) $tmp;
|
||||
}
|
||||
}
|
||||
|
||||
// Merge any additional options in the XML definition.
|
||||
$options = array_merge($options, $custom);
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
JFormHelper::loadFieldClass('list');
|
||||
|
||||
class JFormFieldElementList extends JFormFieldList
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $type = 'ElementList';
|
||||
|
||||
/**
|
||||
* Method to get the field options.
|
||||
*
|
||||
* @return array The field option objects
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
$fieldname = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname);
|
||||
$options = array();
|
||||
|
||||
$tags = 'a,abbr,address,area,article,aside,audio,b,bdi,bdo,blockquote,br,button,canvas,caption,cite,code,col,colgroup,data,datalist,dd,del,details,dfn,dialog,div,dl,dt,em,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,hr,i,img,input,ins,kbd,keygen,label,legend,li,main,map,mark,menu,menuitem,meter,nav,noscript,ol,optgroup,option,output,p,param,pre,progress,q,rb,rp,rt,rtc,ruby,s,samp,section,select,small,source,span,strong,sub,summary,sup,table,tbody,td,template,textarea,tfoot,th,thead,time,tr,track,u,ul,var,video,wbr';
|
||||
|
||||
foreach (explode(',', $tags) as $option) {
|
||||
$value = (string) $option;
|
||||
$text = trim((string) $option);
|
||||
|
||||
$tmp = array(
|
||||
'value' => $value,
|
||||
'text' => JText::alt($text, $fieldname),
|
||||
'disable' => false,
|
||||
'class' => '',
|
||||
'selected' => false,
|
||||
'checked' => false,
|
||||
);
|
||||
|
||||
// Add the option object to the result set.
|
||||
$options[] = (object) $tmp;
|
||||
}
|
||||
|
||||
reset($options);
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
10
administrator/components/com_jce/models/fields/extension.php
Normal file
10
administrator/components/com_jce/models/fields/extension.php
Normal file
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
JFormHelper::loadFieldClass('filetype');
|
||||
|
||||
class JFormFieldExtension extends JFormFieldFiletype
|
||||
{
|
||||
|
||||
}
|
||||
161
administrator/components/com_jce/models/fields/filesystem.php
Normal file
161
administrator/components/com_jce/models/fields/filesystem.php
Normal file
@@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
JFormHelper::loadFieldClass('list');
|
||||
|
||||
class JFormFieldFilesystem extends JFormFieldList
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $type = 'Filesystem';
|
||||
|
||||
/**
|
||||
* Method to attach a JForm object to the field.
|
||||
*
|
||||
* @param SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object
|
||||
* @param mixed $value The form field value to validate
|
||||
* @param string $group The field name group control value. This acts as as an array container for the field.
|
||||
* For example if the field has name="foo" and the group value is set to "bar" then the
|
||||
* full field name would end up being "bar[foo]"
|
||||
*
|
||||
* @return bool True on success
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function setup(SimpleXMLElement $element, $value, $group = null)
|
||||
{
|
||||
$return = parent::setup($element, $value, $group);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the field input markup.
|
||||
*
|
||||
* @return string The field input markup
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function getInput()
|
||||
{
|
||||
$value = $this->value;
|
||||
|
||||
// decode json string
|
||||
if (!empty($value) && is_string($value)) {
|
||||
$value = json_decode($value, true);
|
||||
}
|
||||
|
||||
// default
|
||||
if (empty($value)) {
|
||||
$value = array('name' => $this->default);
|
||||
} else {
|
||||
if (!isset($value['name'])) {
|
||||
$value['name'] = $this->default;
|
||||
}
|
||||
}
|
||||
|
||||
$plugins = $this->getPlugins();
|
||||
$options = $this->getOptions();
|
||||
|
||||
$html = '';
|
||||
$html .= '<div class="controls-row">';
|
||||
|
||||
$html .= '<div class="control-group">';
|
||||
$html .= JHtml::_('select.genericlist', $options, $this->name . '[name]', 'data-toggle="filesystem-options" class="custom-select"', 'value', 'text', $value['name']);
|
||||
$html .= '</div>';
|
||||
|
||||
$html .= '<div class="filesystem-options clearfix">';
|
||||
|
||||
foreach ($plugins as $plugin) {
|
||||
$form = JForm::getInstance('plg_jce_' . $this->name . '_' . $plugin->name, $plugin->manifest, array('control' => $this->name . '[' . $plugin->name . ']'), true, '//extension');
|
||||
|
||||
if ($form) {
|
||||
// get the data for this form, if set
|
||||
$data = isset($value[$plugin->name]) ? $value[$plugin->name] : array();
|
||||
|
||||
// bind data to form
|
||||
$form->bind($data);
|
||||
|
||||
$html .= '<div class="well well-small p-2 bg-light" data-toggle-target="filesystem-options-' . $plugin->name . '">';
|
||||
|
||||
$fields = $form->getFieldset('filesystem.' . $plugin->name);
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$html .= $field->renderField(array('description' => $field->description));
|
||||
}
|
||||
|
||||
$html .= '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
$html .= '</div>';
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the field options.
|
||||
*
|
||||
* @return array The field option objects
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function getPlugins()
|
||||
{
|
||||
static $plugins;
|
||||
|
||||
if (!isset($plugins)) {
|
||||
$plugins = JcePluginsHelper::getExtensions('filesystem');
|
||||
}
|
||||
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the field options.
|
||||
*
|
||||
* @return array The field option objects
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
$fieldname = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname);
|
||||
|
||||
$options = parent::getOptions();
|
||||
|
||||
/*$options[] = array(
|
||||
'value' => '',
|
||||
'text' => JText::_('WF_OPTION_NOT_SET'),
|
||||
);*/
|
||||
|
||||
$plugins = $this->getPlugins();
|
||||
|
||||
foreach ($plugins as $plugin) {
|
||||
$value = (string)$plugin->name;
|
||||
$text = (string)$plugin->title;
|
||||
|
||||
$tmp = array(
|
||||
'value' => $value,
|
||||
'text' => JText::alt($text, $fieldname),
|
||||
'disable' => false,
|
||||
'class' => '',
|
||||
'selected' => false,
|
||||
);
|
||||
|
||||
// Add the option object to the result set.
|
||||
$options[] = (object)$tmp;
|
||||
}
|
||||
|
||||
reset($options);
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
183
administrator/components/com_jce/models/fields/filetype.php
Normal file
183
administrator/components/com_jce/models/fields/filetype.php
Normal file
@@ -0,0 +1,183 @@
|
||||
<?php
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
JFormHelper::loadFieldClass('list');
|
||||
|
||||
class JFormFieldFiletype extends JFormFieldText
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $type = 'Filetype';
|
||||
|
||||
/**
|
||||
* Method to attach a JForm object to the field.
|
||||
*
|
||||
* @param SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object
|
||||
* @param mixed $value The form field value to validate
|
||||
* @param string $group The field name group control value. This acts as as an array container for the field.
|
||||
* For example if the field has name="foo" and the group value is set to "bar" then the
|
||||
* full field name would end up being "bar[foo]"
|
||||
*
|
||||
* @return bool True on success
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function setup(SimpleXMLElement $element, $value, $group = null)
|
||||
{
|
||||
$return = parent::setup($element, $value, $group);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
private static function array_flatten($array, $return)
|
||||
{
|
||||
foreach ($array as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$return = self::array_flatten($value, $return);
|
||||
} else {
|
||||
$return[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
private function mapValue($value)
|
||||
{
|
||||
$data = array();
|
||||
|
||||
// no grouping
|
||||
if (strpos($value, '=') === false) {
|
||||
return array(explode(',', $value));
|
||||
}
|
||||
|
||||
foreach (explode(';', $value) as $group) {
|
||||
$items = explode('=', $group);
|
||||
$name = $items[0];
|
||||
$values = explode(',', $items[1]);
|
||||
|
||||
array_walk($values, function (&$item) use ($name) {
|
||||
if ($name === '-') {
|
||||
$item = '-' . $item;
|
||||
}
|
||||
});
|
||||
|
||||
$data[$name] = $values;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function cleanValue($value)
|
||||
{
|
||||
$data = $this->mapValue($value);
|
||||
// get array values only
|
||||
$values = self::array_flatten($data, array());
|
||||
// convert to string
|
||||
$string = implode(',', $values);
|
||||
// return single array
|
||||
return explode(',', $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the field input markup.
|
||||
*
|
||||
* @return string The field input markup
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function getInput()
|
||||
{
|
||||
// cleanup string
|
||||
$value = htmlspecialchars_decode($this->value);
|
||||
|
||||
// map default values to groups
|
||||
$default = $this->mapValue($this->default);
|
||||
|
||||
// remove leading = if any
|
||||
if ($value && $value[0] === '=') {
|
||||
$value = substr($value, 1);
|
||||
}
|
||||
|
||||
// map values to groups
|
||||
$data = $this->mapValue($value);
|
||||
|
||||
$html = array();
|
||||
|
||||
$html[] = '<div class="filetype">';
|
||||
$html[] = ' <div class="input-append input-group">';
|
||||
|
||||
$html[] = ' <input type="text" value="' . $value . '" disabled class="form-control" />';
|
||||
$html[] = ' <input type="hidden" name="' . $this->name . '" value="' . $value . '" />';
|
||||
$html[] = ' <div class="input-group-append">';
|
||||
$html[] = ' <a class="btn btn-secondary filetype-edit add-on input-group-text" role="button"><i class="icon-edit icon-apply"></i><span role="none">Edit</span></a>';
|
||||
$html[] = ' </div>';
|
||||
$html[] = ' </div>';
|
||||
|
||||
foreach ($data as $group => $items) {
|
||||
$custom = array();
|
||||
|
||||
$html[] = '<dl class="filetype-list">';
|
||||
|
||||
if (is_string($group)) {
|
||||
$checked = '';
|
||||
|
||||
$is_default = isset($default[$group]);
|
||||
|
||||
if (empty($value) || $is_default || (!$is_default && $group[0] !== '-')) {
|
||||
$checked = ' checked="checked"';
|
||||
}
|
||||
|
||||
// clear minus sign
|
||||
$group = str_replace('-', '', $group);
|
||||
|
||||
$groupKey = 'WF_FILEGROUP_' . strtoupper($group);
|
||||
$groupName = JText::_('WF_FILEGROUP_' . strtoupper($group));
|
||||
|
||||
// create simple label if there is no translation
|
||||
if ($groupName === $groupKey) {
|
||||
$groupName = ucfirst($group);
|
||||
}
|
||||
|
||||
$html[] = '<dt class="filetype-group" data-filetype-group="' . $group . '"><label><input type="checkbox" value="' . $group . '"' . $checked . ' />' . $groupName . '</label></dt>';
|
||||
}
|
||||
|
||||
foreach ($items as $item) {
|
||||
$checked = '';
|
||||
|
||||
$item = strtolower($item);
|
||||
|
||||
// clear minus sign
|
||||
$mod = str_replace('-', '', $item);
|
||||
|
||||
$is_default = !empty($default[$group]) && in_array($item, $default[$group]);
|
||||
|
||||
if (empty($value) || $is_default || (!$is_default && $mod === $item)) {
|
||||
$checked = ' checked="checked"';
|
||||
}
|
||||
|
||||
$html[] = '<dd class="filetype-item"><label><input type="checkbox" value="' . $mod . '"' . $checked . ' /><span class="file ' . $mod . '"></span> ' . $mod . '</label>';
|
||||
|
||||
if (!$is_default) {
|
||||
$html[] = '<button class="btn btn-link filetype-remove"><span class="icon-trash"></span></button>';
|
||||
}
|
||||
|
||||
$html[] = '</dd>';
|
||||
}
|
||||
|
||||
$html[] = '<dd class="filetype-item filetype-custom row form-row"><div class="file"></div><input type="text" class="span8 col-md-8 form-control" value="" placeholder="' . JText::_('WF_EXTENSION_MAPPER_TYPE_NEW') . '" /><button class="pull-right float-right btn btn-link filetype-add"><span class="icon-plus"></span></button><button class="pull-right float-right btn btn-link filetype-remove"><span class="icon-trash"></span></button></dd>';
|
||||
|
||||
$html[] = '</dl>';
|
||||
}
|
||||
|
||||
$html[] = ' </div>';
|
||||
|
||||
return implode("\n", $html);
|
||||
}
|
||||
}
|
||||
36
administrator/components/com_jce/models/fields/fontlist.php
Normal file
36
administrator/components/com_jce/models/fields/fontlist.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
JFormHelper::loadFieldClass('filelist');
|
||||
|
||||
class JFormFieldFontList extends JFormFieldFileList
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $type = 'FontList';
|
||||
|
||||
/**
|
||||
* Method to get the field input for a fontlist field.
|
||||
*
|
||||
* @return string The field input
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
protected function getInput()
|
||||
{
|
||||
if (!is_array($this->value) && !empty($this->value)) {
|
||||
// String in format 2,5,4
|
||||
if (is_string($this->value)) {
|
||||
$this->value = explode(',', $this->value);
|
||||
}
|
||||
}
|
||||
|
||||
return parent::getInput();
|
||||
}
|
||||
}
|
||||
139
administrator/components/com_jce/models/fields/fonts.php
Normal file
139
administrator/components/com_jce/models/fields/fonts.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
class JFormFieldFonts extends JFormFieldCheckboxes
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $type = 'Fonts';
|
||||
|
||||
/**
|
||||
* Name of the layout being used to render the field
|
||||
*
|
||||
* @var string
|
||||
* @since 3.5
|
||||
*/
|
||||
protected $layout = 'form.field.fonts';
|
||||
|
||||
/**
|
||||
* Flag to tell the field to always be in multiple values mode.
|
||||
*
|
||||
* @var boolean
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $forceMultiple = false;
|
||||
|
||||
private static $fonts = array(
|
||||
'Andale Mono' => 'andale mono,times',
|
||||
'Arial' => 'arial,helvetica,sans-serif',
|
||||
'Arial Black' => 'arial black,avant garde',
|
||||
'Book Antiqua' => 'book antiqua,palatino',
|
||||
'Comic Sans MS' => 'comic sans ms,sans-serif',
|
||||
'Courier New' => 'courier new,courier',
|
||||
'Georgia' => 'georgia,palatino',
|
||||
'Helvetica' => 'helvetica',
|
||||
'Impact' => 'impact,chicago',
|
||||
'Symbol' => 'symbol',
|
||||
'Tahoma' => 'tahoma,arial,helvetica,sans-serif',
|
||||
'Terminal' => 'terminal,monaco',
|
||||
'Times New Roman' => 'times new roman,times',
|
||||
'Trebuchet MS' => 'trebuchet ms,geneva',
|
||||
'Verdana' => 'verdana,geneva',
|
||||
'Webdings' => 'webdings',
|
||||
'Wingdings' => 'wingdings,zapf dingbats',
|
||||
);
|
||||
|
||||
/**
|
||||
* Allow to override renderer include paths in child fields
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
protected function getLayoutPaths()
|
||||
{
|
||||
return array(JPATH_ADMINISTRATOR . '/components/com_jce/layouts', JPATH_SITE . '/layouts');
|
||||
}
|
||||
|
||||
protected function getOptions()
|
||||
{
|
||||
$fieldname = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname);
|
||||
$options = array();
|
||||
|
||||
if (is_string($this->value)) {
|
||||
$this->value = json_decode(htmlspecialchars_decode($this->value), true);
|
||||
}
|
||||
|
||||
// cast to array
|
||||
$this->value = (array) $this->value;
|
||||
|
||||
$fonts = array();
|
||||
|
||||
// map associative array to array of key value pairs
|
||||
foreach ($this->value as $key => $value) {
|
||||
if (is_numeric($key) && is_array($value)) {
|
||||
$fonts[] = $value;
|
||||
} else {
|
||||
$fonts[] = array($key => $value);
|
||||
}
|
||||
}
|
||||
// array of font names to exclude from default list
|
||||
$exclude = array();
|
||||
// array of custom font key/value pairs
|
||||
$custom = array();
|
||||
|
||||
foreach ($fonts as $font) {
|
||||
list($text) = array_keys($font);
|
||||
list($value) = array_values($font);
|
||||
|
||||
// add to $exclude array
|
||||
$exclude[] = $text;
|
||||
|
||||
$value = htmlspecialchars_decode($value, ENT_QUOTES);
|
||||
|
||||
$isCustom = !in_array($value, array_values(self::$fonts));
|
||||
|
||||
$item = array(
|
||||
'value' => $value,
|
||||
'text' => JText::alt($text, $fieldname),
|
||||
'checked' => true,
|
||||
'custom' => $isCustom,
|
||||
);
|
||||
|
||||
$item = (object) $item;
|
||||
|
||||
if ($isCustom) {
|
||||
$custom[] = $item;
|
||||
} else {
|
||||
$options[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
$checked = empty($exclude) ? true : false;
|
||||
|
||||
// assign empty (unchecked) options for unused fonts
|
||||
foreach (self::$fonts as $text => $value) {
|
||||
|
||||
if (in_array($text, $exclude)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tmp = array(
|
||||
'value' => $value,
|
||||
'text' => JText::alt($text, $fieldname),
|
||||
'checked' => $checked,
|
||||
'custom' => false,
|
||||
);
|
||||
|
||||
$options[] = (object) $tmp;
|
||||
}
|
||||
|
||||
return array_merge($options, $custom);
|
||||
}
|
||||
}
|
||||
80
administrator/components/com_jce/models/fields/heading.php
Normal file
80
administrator/components/com_jce/models/fields/heading.php
Normal file
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2005 - 2015 Open Source Matters, Inc. All rights reserved
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* Form Field class for the Joomla Platform.
|
||||
* Provides spacer markup to be used in form layouts.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
class JFormFieldHeading extends JFormField
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $type = 'Heading';
|
||||
|
||||
/**
|
||||
* Method to get the field input markup for a spacer.
|
||||
* The spacer does not have accept input.
|
||||
*
|
||||
* @return string The field input markup
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function getInput()
|
||||
{
|
||||
return ' ';
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the field label markup for a spacer.
|
||||
* Use the label text or name from the XML element as the spacer or
|
||||
* Use a hr="true" to automatically generate plain hr markup.
|
||||
*
|
||||
* @return string The field label markup
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function getLabel()
|
||||
{
|
||||
$html = array();
|
||||
$class = !empty($this->class) ? ' class="'.$this->class.'"' : '';
|
||||
$html[] = '<h3'.$class.'>';
|
||||
|
||||
// Get the label text from the XML element, defaulting to the element name.
|
||||
$text = $this->element['label'] ? (string) $this->element['label'] : (string) $this->element['name'];
|
||||
$text = $this->translateLabel ? JText::_($text) : $text;
|
||||
|
||||
$html[] = $text;
|
||||
|
||||
$html[] = '</h3>';
|
||||
|
||||
// If a description is specified, use it to build a tooltip.
|
||||
if (!empty($this->description)) {
|
||||
$html[] = '<small>'.JText::_($this->description).'</small>';
|
||||
}
|
||||
|
||||
return implode('', $html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the field title.
|
||||
*
|
||||
* @return string The field title
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function getTitle()
|
||||
{
|
||||
return $this->getLabel();
|
||||
}
|
||||
}
|
||||
139
administrator/components/com_jce/models/fields/keyvalue.php
Normal file
139
administrator/components/com_jce/models/fields/keyvalue.php
Normal file
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
class JFormFieldKeyValue extends JFormField
|
||||
{
|
||||
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 2.8
|
||||
*/
|
||||
protected $type = 'KeyValue';
|
||||
|
||||
/**
|
||||
* Method to attach a JForm object to the field.
|
||||
*
|
||||
* @param SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object.
|
||||
* @param mixed $value The form field value to validate.
|
||||
* @param string $group The field name group control value. This acts as as an array container for the field.
|
||||
* For example if the field has name="foo" and the group value is set to "bar" then the
|
||||
* full field name would end up being "bar[foo]".
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @since 2.8
|
||||
*/
|
||||
public function setup(SimpleXMLElement $element, $value, $group = null)
|
||||
{
|
||||
$return = parent::setup($element, $value, $group);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the field input markup.
|
||||
*
|
||||
* @return string The field input markup.
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function getInput()
|
||||
{
|
||||
$values = $this->value;
|
||||
|
||||
if (is_string($values) && !empty($values)) {
|
||||
$value = htmlspecialchars_decode($this->value);
|
||||
|
||||
$values = json_decode($value, true);
|
||||
|
||||
if (empty($values) && strpos($value, ':') !== false && strpos($value, '{') === false) {
|
||||
$values = array();
|
||||
|
||||
foreach (explode(',', $value) as $item) {
|
||||
$pair = explode(':', $item);
|
||||
|
||||
array_walk($pair, function (&$val) {
|
||||
$val = trim($val, chr(0x22) . chr(0x27) . chr(0x38));
|
||||
});
|
||||
|
||||
$values[] = array(
|
||||
'name' => $pair[0],
|
||||
'value' => $pair[1]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// default
|
||||
if (empty($values)) {
|
||||
$values = array(
|
||||
array(
|
||||
'name' => '',
|
||||
'value' => '',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
$subForm = new JForm($this->name, array('control' => $this->formControl));
|
||||
$children = $this->element->children();
|
||||
|
||||
$subForm->load($children);
|
||||
$subForm->setFields($children);
|
||||
|
||||
$fields = $subForm->getFieldset();
|
||||
|
||||
// And finaly build a main container
|
||||
$str = array();
|
||||
|
||||
foreach ($values as $value) {
|
||||
$str[] = '<div class="form-field-repeatable-item wf-keyvalue">';
|
||||
$str[] = ' <div class="form-field-repeatable-item-group well well-small p-4 bg-light">';
|
||||
|
||||
$n = 0;
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$field->element['multiple'] = true;
|
||||
|
||||
$name = (string) $field->element['name'];
|
||||
|
||||
$val = is_array($value) && isset($value[$name]) ? $value[$name] : '';
|
||||
|
||||
// escape value
|
||||
$field->value = htmlspecialchars_decode($val);
|
||||
|
||||
$field->setup($field->element, $field->value, $this->group);
|
||||
|
||||
// reset id
|
||||
$field->id .= '_' . $n;
|
||||
|
||||
// reset name
|
||||
$field->name = $name;
|
||||
|
||||
$str[] = $field->renderField(array('description' => $field->description));
|
||||
|
||||
$n++;
|
||||
}
|
||||
|
||||
$str[] = ' </div>';
|
||||
|
||||
$str[] = ' <div class="form-field-repeatable-item-control">';
|
||||
$str[] = ' <button class="btn btn-link form-field-repeatable-add" aria-label="' . JText::_('JGLOBAL_FIELD_ADD') . '"><i class="icon icon-plus pull-right float-right"></i></button>';
|
||||
$str[] = ' <button class="btn btn-link form-field-repeatable-remove" aria-label="' . JText::_('JGLOBAL_FIELD_REMOVE') . '"><i class="icon icon-trash pull-right float-right"></i></button>';
|
||||
$str[] = ' </div>';
|
||||
|
||||
$str[] = '</div>';
|
||||
}
|
||||
|
||||
if (!empty($this->value)) {
|
||||
$this->value = htmlspecialchars(json_encode($values));
|
||||
}
|
||||
|
||||
$str[] = '<input type="hidden" name="' . $this->name . '" value="' . $this->value . '" />';
|
||||
|
||||
return implode("", $str);
|
||||
}
|
||||
}
|
||||
109
administrator/components/com_jce/models/fields/mediajce.php
Normal file
109
administrator/components/com_jce/models/fields/mediajce.php
Normal file
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @package JCE
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2017 Open Source Matters, Inc. All rights reserved.
|
||||
* @copyright Copyright (C) 2022 Ryan Demmer All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
use Joomla\CMS\Form\Field\MediaField;
|
||||
use Joomla\CMS\Helper\MediaHelper;
|
||||
|
||||
/**
|
||||
* Provides a modal media selector field for the JCE File Browser
|
||||
*
|
||||
* @since 2.6.17
|
||||
*/
|
||||
class JFormFieldMediaJce extends MediaField
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $type = 'MediaJce';
|
||||
|
||||
/**
|
||||
* Layout to render
|
||||
*
|
||||
* @var string
|
||||
* @since 3.5
|
||||
*/
|
||||
protected $layout = 'joomla.form.field.media';
|
||||
|
||||
/**
|
||||
* Method to attach a JForm object to the field.
|
||||
*
|
||||
* @param SimpleXMLElement $element The SimpleXMLElement object representing the `<field>` tag for the form field object.
|
||||
* @param mixed $value The form field value to validate.
|
||||
* @param string $group The field name group control value. This acts as an array container for the field.
|
||||
* For example if the field has name="foo" and the group value is set to "bar" then the
|
||||
* full field name would end up being "bar[foo]".
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @see JFormField::setup()
|
||||
*/
|
||||
public function setup(SimpleXMLElement $element, $value, $group = null)
|
||||
{
|
||||
$result = parent::setup($element, $value, $group);
|
||||
|
||||
if ($result === true) {
|
||||
$this->mediatype = isset($this->element['mediatype']) ? (string) $this->element['mediatype'] : 'images';
|
||||
|
||||
// Joomla 4 custom layout
|
||||
if (isset($this->types)) {
|
||||
$this->layout = 'joomla.form.field.mediacustom';
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data that is going to be passed to the layout
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getLayoutData()
|
||||
{
|
||||
require_once JPATH_ADMINISTRATOR . '/components/com_jce/helpers/browser.php';
|
||||
|
||||
$config = array(
|
||||
'element' => $this->id,
|
||||
'mediatype' => strtolower($this->mediatype),
|
||||
'converted' => (int) $this->element['converted'] ? true : false
|
||||
);
|
||||
|
||||
if (isset($this->element['plugin'])) {
|
||||
$config['plugin'] = (string) $this->element['plugin'];
|
||||
}
|
||||
|
||||
$options = WFBrowserHelper::getMediaFieldOptions($config);
|
||||
|
||||
$this->link = $options['url'];
|
||||
|
||||
// Get the basic field data
|
||||
$data = parent::getLayoutData();
|
||||
|
||||
// not a valid file browser link
|
||||
if (!$this->link) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$extraData = array(
|
||||
'link' => $this->link,
|
||||
'class' => $this->element['class'] . ' input-medium wf-media-input wf-media-input-active'
|
||||
);
|
||||
|
||||
if ($options['upload'] == 1) {
|
||||
$extraData['class'] .= ' wf-media-input-upload';
|
||||
}
|
||||
|
||||
return array_merge($data, $extraData);
|
||||
}
|
||||
}
|
||||
116
administrator/components/com_jce/models/fields/plugin.php
Normal file
116
administrator/components/com_jce/models/fields/plugin.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
class JFormFieldPlugin extends JFormFieldFileList
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $type = 'Plugin';
|
||||
|
||||
/**
|
||||
* Method to attach a JForm object to the field.
|
||||
*
|
||||
* @param SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object
|
||||
* @param mixed $value The form field value to validate
|
||||
* @param string $group The field name group control value. This acts as as an array container for the field.
|
||||
* For example if the field has name="foo" and the group value is set to "bar" then the
|
||||
* full field name would end up being "bar[foo]"
|
||||
*
|
||||
* @return bool True on success
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function setup(SimpleXMLElement $element, $value, $group = null)
|
||||
{
|
||||
$return = parent::setup($element, $value, $group);
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the field input markup.
|
||||
*
|
||||
* @return string The field input markup
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function getInput()
|
||||
{
|
||||
$value = $this->value;
|
||||
|
||||
// decode json string
|
||||
if (!empty($value) && is_string($value)) {
|
||||
$value = json_decode($value, true);
|
||||
}
|
||||
|
||||
// default
|
||||
if (empty($value)) {
|
||||
$type = $this->default;
|
||||
$path = '';
|
||||
}
|
||||
|
||||
$plugins = $this->getPlugins();
|
||||
|
||||
$html = '<div class="span9">';
|
||||
foreach ($plugins as $plugin) {
|
||||
$name = (string) str_replace($this->name.'-', '', $plugin->element);
|
||||
|
||||
$form = JForm::getInstance('plg_jce_'.$plugin->element, $plugin->manifest, array('control' => $this->name.'['.$name.']'), true, '//extension');
|
||||
|
||||
if ($form) {
|
||||
$html .= $form->renderFieldset('extension.'.$name.'.'.$name);
|
||||
}
|
||||
}
|
||||
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the field options.
|
||||
*
|
||||
* @return array The field option objects
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function getPlugins()
|
||||
{
|
||||
static $plugins;
|
||||
|
||||
if (!isset($plugins)) {
|
||||
$language = JFactory::getLanguage();
|
||||
|
||||
$db = JFactory::getDbo();
|
||||
$query = $db->getQuery(true)
|
||||
->select('name, element')
|
||||
->from('#__extensions')
|
||||
->where('enabled = 1')
|
||||
->where('type ='.$db->quote('plugin'))
|
||||
->where('state IN (0,1)')
|
||||
->where('folder = '.$db->quote('jce'))
|
||||
->where('element LIKE '.$db->quote($this->name.'-%'))
|
||||
->order('ordering');
|
||||
|
||||
$plugins = $db->setQuery($query)->loadObjectList();
|
||||
|
||||
foreach ($plugins as $plugin) {
|
||||
$name = str_replace($this->name, '', $plugin->element);
|
||||
|
||||
// load language file
|
||||
$language->load('plg_jce_'.$this->name.'_'.$name, JPATH_ADMINISTRATOR);
|
||||
|
||||
// create manifest path
|
||||
$plugin->manifest = JPATH_PLUGINS.'/jce/'.$plugin->element.'/'.$plugin->element.'.xml';
|
||||
}
|
||||
}
|
||||
|
||||
return $plugins;
|
||||
}
|
||||
}
|
||||
44
administrator/components/com_jce/models/fields/popups.php
Normal file
44
administrator/components/com_jce/models/fields/popups.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
JFormHelper::loadFieldClass('list');
|
||||
|
||||
class JFormFieldPopups extends JFormFieldList
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $type = 'Popups';
|
||||
|
||||
/**
|
||||
* Method to get a list of options for a list input.
|
||||
*
|
||||
* @return array An array of JHtml options
|
||||
*
|
||||
* @since 11.4
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
$extensions = JcePluginsHelper::getExtensions('popups');
|
||||
|
||||
$options = array();
|
||||
|
||||
foreach ($extensions as $item) {
|
||||
$option = new StdClass;
|
||||
|
||||
$option->text = JText::_($item->title, true);
|
||||
$option->disable = '';
|
||||
$option->value = $item->name;
|
||||
|
||||
$options[] = $option;
|
||||
}
|
||||
|
||||
// Merge any additional options in the XML definition.
|
||||
return array_merge(parent::getOptions(), $options);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (C) 2005 - 2014 Open Source Matters, Inc. All rights reserved
|
||||
* @license GNU General Public License version 2 or later; see LICENSE.txt
|
||||
*/
|
||||
defined('JPATH_BASE') or die;
|
||||
|
||||
JFormHelper::loadFieldClass('ordering');
|
||||
|
||||
/**
|
||||
* Supports an HTML select list of plugins.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class JFormFieldProfileordering extends JFormFieldOrdering
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected $type = 'Profileordering';
|
||||
|
||||
/**
|
||||
* Builds the query for the ordering list.
|
||||
*
|
||||
* @return JDatabaseQuery The query for the ordering form field
|
||||
*/
|
||||
protected function getQuery()
|
||||
{
|
||||
$db = JFactory::getDbo();
|
||||
|
||||
// Build the query for the ordering list.
|
||||
$query = $db->getQuery(true)
|
||||
->select(array($db->quoteName('ordering', 'value'), $db->quoteName('name', 'text'), $db->quote('id')))
|
||||
->from($db->quoteName('#__wf_profiles'))
|
||||
->order('ordering');
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the current Item's Id.
|
||||
*
|
||||
* @return int The current item ID
|
||||
*/
|
||||
protected function getItemId()
|
||||
{
|
||||
return (int) $this->form->getValue('id');
|
||||
}
|
||||
}
|
||||
111
administrator/components/com_jce/models/fields/repeatable.php
Normal file
111
administrator/components/com_jce/models/fields/repeatable.php
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
/**
|
||||
* @package JCE
|
||||
* @subpackage Component
|
||||
*
|
||||
* @copyright Copyright (C) 2005 - 2019 Open Source Matters, Inc. All rights reserved.
|
||||
* @copyright Copyright (C) 2006 - 2020 Ryan Demmer. All rights reserved.
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* Form Field class for the JCE.
|
||||
* Display a field with a repeatable set of defined sub fields
|
||||
*
|
||||
* @since 2.7
|
||||
*/
|
||||
class JFormFieldRepeatable extends JFormField
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.7
|
||||
*/
|
||||
protected $type = 'Repeatable';
|
||||
|
||||
/**
|
||||
* Method to get the field input markup.
|
||||
*
|
||||
* @return string The field input markup.
|
||||
*
|
||||
* @since 2.7
|
||||
*/
|
||||
protected function getInput()
|
||||
{
|
||||
$subForm = new JForm($this->name, array('control' => $this->formControl));
|
||||
$children = $this->element->children();
|
||||
$subForm->load($children);
|
||||
$subForm->setFields($children);
|
||||
|
||||
// And finaly build a main container
|
||||
$str = array();
|
||||
|
||||
$values = $this->value;
|
||||
|
||||
// explode to array if string
|
||||
if (is_string($values)) {
|
||||
$values = explode(',', $values);
|
||||
}
|
||||
|
||||
$fields = $subForm->getFieldset();
|
||||
|
||||
$str[] = '<div class="form-field-repeatable">';
|
||||
|
||||
foreach ($values as $value) {
|
||||
$class = '';
|
||||
|
||||
// highlight grouped fields
|
||||
if (count($fields) > 1) {
|
||||
$class = ' well well-small p-4 bg-light';
|
||||
}
|
||||
|
||||
$str[] = '<div class="form-field-repeatable-item">';
|
||||
$str[] = ' <div class="form-field-repeatable-item-group' . $class . '">';
|
||||
|
||||
$n = 0;
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$field->element['multiple'] = true;
|
||||
|
||||
// substitute for repeatable element
|
||||
$field->element['name'] = (string) $this->element['name'];
|
||||
|
||||
if (is_array($value)) {
|
||||
$value = isset($value[$n]) ? $value[$n] : $value[0];
|
||||
}
|
||||
|
||||
// escape value
|
||||
$field->value = htmlspecialchars($value, ENT_COMPAT, 'UTF-8');
|
||||
|
||||
$field->setup($field->element, $field->value, $this->group);
|
||||
|
||||
// reset id
|
||||
$field->id .= '_' . $n;
|
||||
|
||||
if (strpos($field->name, '[]') === false) {
|
||||
$field->name .= '[]';
|
||||
}
|
||||
|
||||
$str[] = $field->renderField(array('description' => $field->description));
|
||||
|
||||
$n++;
|
||||
}
|
||||
|
||||
$str[] = ' </div>';
|
||||
|
||||
$str[] = ' <div class="form-field-repeatable-item-control">';
|
||||
$str[] = ' <button class="btn btn-link form-field-repeatable-add" aria-label="' . JText::_('JGLOBAL_FIELD_ADD') . '"><i class="icon icon-plus pull-right float-right"></i></button>';
|
||||
$str[] = ' <button class="btn btn-link form-field-repeatable-remove" aria-label="' . JText::_('JGLOBAL_FIELD_REMOVE') . '"><i class="icon icon-trash pull-right float-right"></i></button>';
|
||||
$str[] = ' </div>';
|
||||
|
||||
$str[] = '</div>';
|
||||
}
|
||||
|
||||
$str[] = '</div>';
|
||||
|
||||
return implode("", $str);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
JFormHelper::loadFieldClass('plugins');
|
||||
|
||||
class JFormFieldSearchPlugins extends JFormFieldPlugins
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $type = 'SearchPlugins';
|
||||
|
||||
/**
|
||||
* Method to attach a JForm object to the field.
|
||||
*
|
||||
* @param SimpleXMLElement $element The SimpleXMLElement object representing the `<field>` tag for the form field object.
|
||||
* @param mixed $value The form field value to validate.
|
||||
* @param string $group The field name group control value. This acts as an array container for the field.
|
||||
* For example if the field has name="foo" and the group value is set to "bar" then the
|
||||
* full field name would end up being "bar[foo]".
|
||||
*
|
||||
* @return boolean True on success.
|
||||
*
|
||||
* @see JFormField::setup()
|
||||
* @since 3.2
|
||||
*/
|
||||
public function setup(SimpleXMLElement $element, $value, $group = null)
|
||||
{
|
||||
if (is_string($value) && strpos($value, ',') !== false)
|
||||
{
|
||||
$value = explode(',', $value);
|
||||
}
|
||||
|
||||
$return = parent::setup($element, $value, $group);
|
||||
|
||||
if ($return)
|
||||
{
|
||||
$this->folder = 'search';
|
||||
$this->useaccess = true;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a list of options for a list input.
|
||||
*
|
||||
* @return array An array of JHtml options
|
||||
*
|
||||
* @since 11.4
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
$options = array();
|
||||
$default = explode(',', $this->default);
|
||||
|
||||
foreach (parent::getOptions() as $item) {
|
||||
if (in_array($item->value, $default)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip "newsfeeds"
|
||||
if ($item->value == 'newsfeeds') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$options[] = $item;
|
||||
}
|
||||
|
||||
foreach ($default as $name) {
|
||||
if (!is_dir(JPATH_SITE . '/components/com_jce/editor/extensions/search/adapter/' . $name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$option = new StdClass;
|
||||
|
||||
$option->text = JText::_('PLG_SEARCH_' . strtoupper($name) . '_' . strtoupper($name), true);
|
||||
$option->disable = '';
|
||||
$option->value = $name;
|
||||
|
||||
$options[] = $option;
|
||||
}
|
||||
|
||||
// Merge any additional options in the XML definition.
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
class JFormFieldSortableCheckboxes extends JFormFieldCheckboxes
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 2.8.16
|
||||
*/
|
||||
protected $type = 'SortableCheckboxes';
|
||||
|
||||
/**
|
||||
* Method to attach a JForm object to the field.
|
||||
*
|
||||
* @param SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object
|
||||
* @param mixed $value The form field value to validate
|
||||
* @param string $group The field name group control value. This acts as as an array container for the field.
|
||||
* For example if the field has name="foo" and the group value is set to "bar" then the
|
||||
* full field name would end up being "bar[foo]"
|
||||
*
|
||||
* @return bool True on success
|
||||
*
|
||||
* @since 2.8.16
|
||||
*/
|
||||
public function setup(SimpleXMLElement $element, $value, $group = null)
|
||||
{
|
||||
$return = parent::setup($element, $value, $group);
|
||||
|
||||
$this->class = trim($this->class . ' sortable');
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
private function getOptionFromValue($value)
|
||||
{
|
||||
$options = parent::getOptions();
|
||||
|
||||
foreach($options as $option) {
|
||||
if ($option->value == $value) {
|
||||
return $option;
|
||||
}
|
||||
}
|
||||
|
||||
return (object) array(
|
||||
'value' => $value,
|
||||
'text' => $value
|
||||
);
|
||||
}
|
||||
|
||||
protected function getOptions()
|
||||
{
|
||||
$options = parent::getOptions();
|
||||
|
||||
$values = is_array($this->value) ? $this->value : explode(',', $this->value);
|
||||
|
||||
if (!empty($values)) {
|
||||
$custom = array();
|
||||
|
||||
foreach ($values as $value) {
|
||||
$tmp = $this->getOptionFromValue($value);
|
||||
$tmp->checked = true;
|
||||
|
||||
$custom[] = $tmp;
|
||||
}
|
||||
|
||||
// add default options not checked to the end of the options array
|
||||
foreach($options as $option) {
|
||||
if (!in_array($option->value, $values)) {
|
||||
$custom[] = $option;
|
||||
}
|
||||
}
|
||||
|
||||
return $custom;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
129
administrator/components/com_jce/models/fields/styleformat.php
Normal file
129
administrator/components/com_jce/models/fields/styleformat.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?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_BASE') or die;
|
||||
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
/**
|
||||
* Renders a select element.
|
||||
*/
|
||||
class JFormFieldStyleFormat extends JFormField
|
||||
{
|
||||
/*
|
||||
* Element type
|
||||
*
|
||||
* @access protected
|
||||
* @var string
|
||||
*/
|
||||
protected $type = 'StyleFormat';
|
||||
|
||||
protected function getInput()
|
||||
{
|
||||
$wf = WFApplication::getInstance();
|
||||
|
||||
$output = array();
|
||||
|
||||
// default item list (remove "attributes" for now)
|
||||
$default = array('title' => '', 'element' => '', 'selector' => '', 'classes' => '', 'styles' => '', 'attributes' => '');
|
||||
|
||||
// pass to items
|
||||
$items = $this->value;
|
||||
|
||||
if (is_string($items)) {
|
||||
$items = json_decode(htmlspecialchars_decode($this->value), true);
|
||||
}
|
||||
|
||||
// cast to array
|
||||
$items = (array) $items;
|
||||
|
||||
/* Convert legacy styles */
|
||||
$theme_advanced_styles = $wf->getParam('editor.theme_advanced_styles', '');
|
||||
|
||||
if (!empty($theme_advanced_styles)) {
|
||||
foreach (explode(',', $theme_advanced_styles) as $styles) {
|
||||
$style = json_decode('{' . preg_replace('#([^=]+)=([^=]+)#', '"title":"$1","classes":"$2"', $styles) . '}', true);
|
||||
|
||||
if ($style) {
|
||||
$items[] = $style;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create default array if no items
|
||||
if (empty($items)) {
|
||||
$items = array($default);
|
||||
}
|
||||
|
||||
$subForm = new JForm($this->name);
|
||||
|
||||
// editor manifest
|
||||
$manifest = JPATH_ADMINISTRATOR . '/components/com_jce/models/forms/styleformat.xml';
|
||||
$xml = simplexml_load_file($manifest);
|
||||
$subForm->load($xml);
|
||||
|
||||
$fields = $subForm->getFieldset();
|
||||
|
||||
$output[] = '<div class="styleformat-list">';
|
||||
|
||||
$x = 0;
|
||||
|
||||
foreach ($items as $item) {
|
||||
$elements = array('<div class="styleformat">');
|
||||
|
||||
foreach($fields as $field) {
|
||||
$key = (string) $field->element['name'];
|
||||
|
||||
// default value
|
||||
$field->value = "";
|
||||
|
||||
if (array_key_exists($key, $item)) {
|
||||
$field->value = htmlspecialchars_decode($item[$key], ENT_QUOTES);
|
||||
}
|
||||
|
||||
$field->setup($field->element, $field->value, $this->group);
|
||||
$field->id = '';
|
||||
$field->name = '';
|
||||
|
||||
$elements[] = '<div class="styleformat-item-' . $key . '" data-key="' . $key . '">' . $field->renderField(array('description' => $field->description)) . '</div>';
|
||||
}
|
||||
|
||||
$elements[] = '<div class="styleformat-header">';
|
||||
|
||||
// handle
|
||||
$elements[] = '<span class="styleformat-item-handle"></span>';
|
||||
// delete button
|
||||
$elements[] = '<button class="styleformat-item-trash btn btn-link pull-right float-right"><i class="icon icon-trash"></i></button>';
|
||||
// collapse
|
||||
$elements[] = '<button class="close collapse btn btn-link"><i class="icon icon-chevron-up"></i><i class="icon icon-chevron-down"></i></button>';
|
||||
|
||||
$elements[] = '</div>';
|
||||
|
||||
$elements[] = '</div>';
|
||||
|
||||
$output[] = implode('', $elements);
|
||||
|
||||
$x++;
|
||||
}
|
||||
|
||||
$output[] = '<button class="btn btn-link styleformat-item-plus"><span class="span10 col-md-10 text-left">' . JText::_('WF_STYLEFORMAT_NEW') . '</span><i class="icon icon-plus pull-right float-right"></i></button>';
|
||||
|
||||
// hidden field
|
||||
$output[] = '<input type="hidden" name="' . $this->name . '" value="" />';
|
||||
|
||||
if (!empty($theme_advanced_styles)) {
|
||||
$output[] = '<input type="hidden" name="' . $this->getName('theme_advanced_styles') . '" value="" class="isdirty" />';
|
||||
}
|
||||
|
||||
$output[] = '</div>';
|
||||
|
||||
return implode("\n", $output);
|
||||
}
|
||||
}
|
||||
68
administrator/components/com_jce/models/fields/taglist.php
Normal file
68
administrator/components/com_jce/models/fields/taglist.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
JFormHelper::loadFieldClass('list');
|
||||
|
||||
class JFormFieldTagList extends JFormFieldList
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public $type = 'TagList';
|
||||
|
||||
/**
|
||||
* Name of the layout being used to render the field
|
||||
*
|
||||
* @var string
|
||||
* @since 4.0.0
|
||||
*/
|
||||
//protected $layout = 'joomla.form.field.tag';
|
||||
|
||||
/**
|
||||
* Method to get the field input for a tag field.
|
||||
*
|
||||
* @return string The field input.
|
||||
*
|
||||
* @since 3.1
|
||||
*/
|
||||
/*protected function getInput()
|
||||
{
|
||||
$data = $this->getLayoutData();
|
||||
|
||||
// Get the field id
|
||||
$id = isset($this->element['id']) ? $this->element['id'] : null;
|
||||
$cssId = '#' . $this->getId($id, $this->element['name']);
|
||||
|
||||
\JHtml::_('tag.ajaxfield', $cssId, true);
|
||||
|
||||
if (!\is_array($this->value) && !empty($this->value))
|
||||
{
|
||||
// String in format 2,5,4
|
||||
if (\is_string($this->value))
|
||||
{
|
||||
$this->value = explode(',', $this->value);
|
||||
}
|
||||
|
||||
// Integer is given
|
||||
if (\is_int($this->value))
|
||||
{
|
||||
$this->value = array($this->value);
|
||||
}
|
||||
|
||||
$data['value'] = $this->value;
|
||||
}
|
||||
|
||||
$data['remoteSearch'] = false;
|
||||
$data['options'] = $this->getOptions();
|
||||
$data['isNested'] = false;
|
||||
$data['allowCustom'] = true;
|
||||
$data['minTermLength'] = (int) 3;
|
||||
|
||||
return $this->getRenderer($this->layout)->render($data);
|
||||
}*/
|
||||
}
|
||||
128
administrator/components/com_jce/models/fields/uploadmaxsize.php
Normal file
128
administrator/components/com_jce/models/fields/uploadmaxsize.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved
|
||||
* @license GNU General Public License version 2 or later; see LICENSE
|
||||
*/
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
JFormHelper::loadFieldClass('number');
|
||||
|
||||
/**
|
||||
* Form Field class for the Joomla Platform.
|
||||
* Supports a one line text field.
|
||||
*
|
||||
* @link http://www.w3.org/TR/html-markup/input.text.html#input.text
|
||||
* @since 11.1
|
||||
*/
|
||||
class JFormFieldUploadMaxSize extends JFormFieldNumber
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $type = 'uploadmaxsize';
|
||||
|
||||
/**
|
||||
* Method to get the field input markup.
|
||||
*
|
||||
* @return string The field input markup
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function getInput()
|
||||
{
|
||||
$this->max = (int) $this->getUploadValue();
|
||||
$this->class = trim($this->class.' input-small');
|
||||
|
||||
$html = '<div class="input-append input-group">';
|
||||
|
||||
$html .= parent::getInput();
|
||||
$html .= ' <div class="input-group-append">';
|
||||
$html .= ' <span class="add-on input-group-text">Kb</span>';
|
||||
$html .= ' </div>';
|
||||
$html .= ' <small class="help-inline form-text"> <em>'.JText::_('WF_SERVER_UPLOAD_SIZE').' : '.$this->getUploadValue().'</em></small>';
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
public function getUploadValue()
|
||||
{
|
||||
$upload = trim(ini_get('upload_max_filesize'));
|
||||
$post = trim(ini_get('post_max_size'));
|
||||
|
||||
$upload = $this->convertValue($upload);
|
||||
$post = $this->convertValue($post);
|
||||
|
||||
if (intval($post) === 0) {
|
||||
return $upload;
|
||||
}
|
||||
|
||||
if (intval($upload) < intval($post)) {
|
||||
return $upload;
|
||||
}
|
||||
|
||||
return $post;
|
||||
}
|
||||
|
||||
public function convertValue($value)
|
||||
{
|
||||
$unit = 'KB';
|
||||
$prefix = '';
|
||||
|
||||
preg_match('#([0-9]+)\s?([a-z]*)#i', $value, $matches);
|
||||
|
||||
// get unit
|
||||
if (isset($matches[2])) {
|
||||
$prefix = $matches[2];
|
||||
|
||||
// extract first character only, eg: g, m, k
|
||||
if ($prefix) {
|
||||
$prefix = strtolower($prefix[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// get value
|
||||
if (isset($matches[1])) {
|
||||
$value = (int) $matches[1];
|
||||
}
|
||||
|
||||
$value = intval($value);
|
||||
|
||||
// Convert to bytes
|
||||
switch ($prefix) {
|
||||
case 'g':
|
||||
$value *= 1073741824;
|
||||
break;
|
||||
case 'm':
|
||||
$value *= 1048576;
|
||||
break;
|
||||
case 'k':
|
||||
$value *= 1024;
|
||||
break;
|
||||
}
|
||||
|
||||
// Convert to unit value
|
||||
switch (strtolower($unit[0])) {
|
||||
case 'g':
|
||||
$value /= 1073741824;
|
||||
break;
|
||||
case 'm':
|
||||
$value /= 1048576;
|
||||
break;
|
||||
case 'k':
|
||||
$value /= 1024;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($unit) {
|
||||
return (int) $value . ' ' . $unit;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
123
administrator/components/com_jce/models/fields/users.php
Normal file
123
administrator/components/com_jce/models/fields/users.php
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
/**
|
||||
* Field to select a user ID from a modal list.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class JFormFieldUsers extends JFormFieldUser
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
* @since 2.7
|
||||
*/
|
||||
public $type = 'Users';
|
||||
|
||||
/**
|
||||
* Method to get the user field input markup.
|
||||
*
|
||||
* @return string The field input markup.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function getInput()
|
||||
{
|
||||
if (empty($this->layout))
|
||||
{
|
||||
throw new \UnexpectedValueException(sprintf('%s has no layout assigned.', $this->name));
|
||||
}
|
||||
|
||||
$options = $this->getOptions();
|
||||
|
||||
$name = $this->name;
|
||||
|
||||
// clear name
|
||||
$this->name = "";
|
||||
|
||||
// set onchange to update
|
||||
$this->onchange = "(function(){WfSelectUsers();})();";
|
||||
|
||||
// remove autocomplete
|
||||
$this->autocomplete = false;
|
||||
|
||||
// clear value
|
||||
$this->value = "";
|
||||
|
||||
$html = $this->getRenderer($this->layout)->render($this->getLayoutData());
|
||||
$html .= '<div class="users-select">';
|
||||
|
||||
// add "joomla-field-fancy-select" manually for Joomla 4
|
||||
$html .= '<joomla-field-fancy-select placeholder="...">';
|
||||
$html .= '<select name="' . $name . '" id="' . $this->id . '_select" class="custom-select" data-placeholder="..." multiple>';
|
||||
|
||||
foreach ($options as $option) {
|
||||
$html .= '<option value="' . $option->value . '" selected>' . $option->text . '</option>';
|
||||
}
|
||||
|
||||
$html .= '</select>';
|
||||
$html .= '</joomla-field-fancy-select>';
|
||||
$html .= '</div>';
|
||||
|
||||
return $html;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow to override renderer include paths in child fields
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @since 3.5
|
||||
*/
|
||||
protected function getLayoutPaths()
|
||||
{
|
||||
return array(JPATH_ADMINISTRATOR . '/components/com_jce/layouts', JPATH_SITE . '/layouts');
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the field options.
|
||||
*
|
||||
* @return array The field option objects
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected function getOptions()
|
||||
{
|
||||
$options = array();
|
||||
|
||||
if (empty($this->value)) {
|
||||
return $options;
|
||||
}
|
||||
|
||||
$fieldname = preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname);
|
||||
$table = JTable::getInstance('user');
|
||||
|
||||
// clean value
|
||||
$this->value = str_replace('"', '', $this->value);
|
||||
|
||||
foreach (explode(',', $this->value) as $id) {
|
||||
if (empty($id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($table->load((int) $id)) {
|
||||
$text = htmlspecialchars($table->name, ENT_COMPAT, 'UTF-8');
|
||||
$text = JText::alt($text, $fieldname);
|
||||
|
||||
$tmp = array(
|
||||
'value' => $id,
|
||||
'text' => $text
|
||||
);
|
||||
|
||||
// Add the option object to the result set.
|
||||
$options[] = (object) $tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
}
|
||||
39
administrator/components/com_jce/models/fields/yesno.php
Normal file
39
administrator/components/com_jce/models/fields/yesno.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
defined('JPATH_PLATFORM') or die;
|
||||
|
||||
JFormHelper::loadFieldClass('radio');
|
||||
|
||||
class JFormFieldYesNo extends JFormFieldRadio
|
||||
{
|
||||
/**
|
||||
* The form field type.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
protected $type = 'YesNo';
|
||||
|
||||
/**
|
||||
* Method to attach a JForm object to the field.
|
||||
*
|
||||
* @param SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object
|
||||
* @param mixed $value The form field value to validate
|
||||
* @param string $group The field name group control value. This acts as as an array container for the field.
|
||||
* For example if the field has name="foo" and the group value is set to "bar" then the
|
||||
* full field name would end up being "bar[foo]"
|
||||
*
|
||||
* @return bool True on success
|
||||
*
|
||||
* @since 11.1
|
||||
*/
|
||||
public function setup(SimpleXMLElement $element, $value, $group = null)
|
||||
{
|
||||
$return = parent::setup($element, $value, $group);
|
||||
|
||||
$this->class = trim($this->class.' btn-group btn-group-yesno');
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
96
administrator/components/com_jce/models/forms/config.xml
Normal file
96
administrator/components/com_jce/models/forms/config.xml
Normal file
@@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<form>
|
||||
<fields name="params">
|
||||
<fieldset name="config" label="Global Configuration">
|
||||
|
||||
<field name="verify_html" type="radio" default="1" label="WF_PARAM_CLEANUP" description="WF_PARAM_CLEANUP_DESC" class="btn-group btn-group-yesno" filter="integer">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
|
||||
<field name="schema" type="list" default="mixed" label="WF_PARAM_DOCTYPE" description="WF_PARAM_DOCTYPE_DESC">
|
||||
<option value="html4">HTML4</option>
|
||||
<option value="mixed">WF_PARAM_DOCTYPE_MIXED</option>
|
||||
<option value="html5">HTML5</option>
|
||||
</field>
|
||||
|
||||
<field name="entity_encoding" type="list" default="raw" label="WF_PARAM_ENTITY_ENCODING" description="WF_PARAM_ENTITY_ENCODING_DESC">
|
||||
<option value="raw">UTF-8</option>
|
||||
<option value="named">WF_PARAM_NAMED</option>
|
||||
<option value="numeric">WF_PARAM_NUMERIC</option>
|
||||
</field>
|
||||
|
||||
<field name="keep_nbsp" type="radio" default="1" label="WF_PARAM_KEEP_NBSP" description="WF_PARAM_KEEP_NBSP_DESC" class="btn-group btn-group-yesno" filter="integer">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
|
||||
<field name="pad_empty_tags" type="radio" default="1" label="WF_PARAM_PAD_EMPTY_TAGS" description="WF_PARAM_PAD_EMPTY_TAGS_DESC" class="btn-group btn-group-yesno" filter="integer">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
|
||||
<field name="spacer1" type="spacer" hr="true" />
|
||||
|
||||
<field name="forced_root_block" type="list" default="p" label="WF_PARAM_ROOT_BLOCK" description="WF_PARAM_ROOT_BLOCK_DESC">
|
||||
<option value="p">WF_OPTION_PARAGRAPH</option>
|
||||
<option value="div">WF_OPTION_DIV</option>
|
||||
<option value="forced_root_block:p|force_block_newlines:0">WF_OPTION_PARAGRAPH_LINEBREAK</option>
|
||||
<option value="forced_root_block:div|force_block_newlines:0">WF_OPTION_DIV_LINEBREAK</option>
|
||||
|
||||
<option value="forced_root_block:0|force_block_newlines:1">WF_OPTION_PARAGRAPH_MIXED</option>
|
||||
<option value="0">WF_OPTION_LINEBREAK</option>
|
||||
</field>
|
||||
|
||||
<field name="content_style_reset" type="list" default="auto" label="WF_PARAM_EDITOR_STYLE_RESET" description="WF_PARAM_EDITOR_STYLE_RESET_DESC">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
<option value="auto">WF_OPTION_AUTO</option>
|
||||
</field>
|
||||
|
||||
<field name="content_css" type="list" default="1" label="WF_PARAM_EDITOR_GLOBAL_CSS" description="WF_PARAM_EDITOR_GLOBAL_CSS_DESC" filter="integer">
|
||||
<option value="0">WF_PARAM_CSS_CUSTOM</option>
|
||||
<option value="1">WF_PARAM_CSS_TEMPLATE</option>
|
||||
<option value="2">WF_OPTION_DEFAULT</option>
|
||||
</field>
|
||||
|
||||
<field name="content_css_custom" type="repeatable" default="" label="WF_PARAM_CSS_CUSTOM" description="WF_PARAM_CSS_CUSTOM_DESC" showon="content_css:0">
|
||||
<field type="text" size="50" hiddenLabel="true" hint="eg: templates/$template/css/content.css" />
|
||||
</field>
|
||||
|
||||
<!--field name="content_css_custom" type="textarea" rows="2" class="input-xlarge" default="" hint="eg: templates/$template/css/content.css" label="WF_PARAM_CSS_CUSTOM" description="WF_PARAM_CSS_CUSTOM_DESC" showon="content_css:0" /-->
|
||||
<field name="body_class" type="text" default="" placeholder="eg: content" label="WF_PARAM_EDITOR_BODY_CLASS" description="WF_PARAM_EDITOR_BODY_CLASS_DESC" />
|
||||
|
||||
<field name="spacer2" type="spacer" hr="true" />
|
||||
|
||||
<field name="compress_javascript" type="radio" default="0" label="WF_PARAM_COMPRESS_JAVASCRIPT" description="WF_PARAM_COMPRESS_JAVASCRIPT_DESC" class="btn-group btn-group-yesno" filter="integer">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
|
||||
<field name="compress_css" type="radio" default="0" label="WF_PARAM_COMPRESS_CSS" description="WF_PARAM_COMPRESS_CSS_DESC" class="btn-group btn-group-yesno" filter="integer">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
|
||||
<field name="compress_cache_validation" type="radio" default="1" label="WF_PARAM_COMPRESS_CACHE_VALIDATION" description="WF_PARAM_COMPRESS_CACHE_VALIDATION_DESC" class="btn-group btn-group-yesno" filter="integer">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
|
||||
<field name="spacer3" type="spacer" hr="true" />
|
||||
|
||||
<field name="use_cookies" type="radio" default="1" label="WF_PARAM_USE_COOKIES" description="WF_PARAM_USE_COOKIES_DESC" class="btn-group btn-group-yesno" filter="integer">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
|
||||
<field name="custom_config" type="keyvalue" default="" label="WF_PARAM_CUSTOM_CONFIG" description="WF_PARAM_CUSTOM_CONFIG_DESC">
|
||||
<field type="text" name="name" label="WF_PROFILES_CUSTOM_KEY" />
|
||||
<field type="text" name="value" label="WF_PROFILES_CUSTOM_VALUE" />
|
||||
</field>
|
||||
|
||||
</fieldset>
|
||||
|
||||
</fields>
|
||||
</form>
|
||||
224
administrator/components/com_jce/models/forms/editor.xml
Normal file
224
administrator/components/com_jce/models/forms/editor.xml
Normal file
@@ -0,0 +1,224 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<form>
|
||||
<fields name="editor">
|
||||
<fieldset name="editor.features" addfieldpath="/administrator/components/com_categories/models/fields">
|
||||
<field name="width" type="text" size="5" default="" placeholder="auto" label="WF_PARAM_EDITOR_WIDTH" description="WF_PARAM_EDITOR_WIDTH_DESC" />
|
||||
<field name="height" type="text" size="5" default="" placeholder="auto" label="WF_PARAM_EDITOR_HEIGHT" description="WF_PARAM_EDITOR_HEIGHT_DESC" />
|
||||
<field name="toolbar_theme" type="list" default="modern" label="WF_PARAM_EDITOR_TOOLBAR_THEME" description="WF_PARAM_EDITOR_TOOLBAR_THEME_DESC">
|
||||
<option value="modern">WF_PARAM_EDITOR_SKIN_RETINA</option>
|
||||
<option value="modern.touch">WF_PARAM_EDITOR_SKIN_RETINA_TOUCH</option>
|
||||
<!--option value="modern.dark">WF_PARAM_EDITOR_SKIN_RETINA_DARK</option-->
|
||||
<option value="default">WF_PARAM_EDITOR_SKIN_CLASSIC</option>
|
||||
<option value="default.touch">WF_PARAM_EDITOR_SKIN_CLASSIC_TOUCH</option>
|
||||
<option value="o2k7">WF_PARAM_EDITOR_SKIN_OFFICE_BLUE</option>
|
||||
<option value="o2k7.silver">WF_PARAM_EDITOR_SKIN_OFFICE_SILVER</option>
|
||||
<option value="o2k7.black">WF_PARAM_EDITOR_SKIN_OFFICE_BLACK</option>
|
||||
</field>
|
||||
<field name="toolbar_align" type="list" default="left" label="WF_PARAM_EDITOR_TOOLBAR_ALIGN" description="WF_PARAM_EDITOR_TOOLBAR_ALIGN_DESC">
|
||||
<option value="left">WF_OPTION_LEFT</option>
|
||||
<option value="center">WF_OPTION_CENTER</option>
|
||||
<option value="right">WF_OPTION_RIGHT</option>
|
||||
</field>
|
||||
<field name="toolbar_location" type="list" default="top" label="WF_PARAM_EDITOR_TOOLBAR_LOCATION" description="WF_PARAM_EDITOR_TOOLBAR_LOCATION_DESC">
|
||||
<option value="top">WF_OPTION_TOP</option>
|
||||
<option value="bottom">WF_OPTION_BOTTOM</option>
|
||||
</field>
|
||||
<field name="statusbar_location" type="list" default="bottom" label="WF_PARAM_EDITOR_STATUSBAR_LOCATION" description="WF_PARAM_EDITOR_STATUSBAR_LOCATION_DESC">
|
||||
<option value="top">WF_OPTION_TOP</option>
|
||||
<option value="bottom">WF_OPTION_BOTTOM</option>
|
||||
<option value="none">JNONE</option>
|
||||
</field>
|
||||
<field name="path" type="yesno" default="1" label="WF_PARAM_EDITOR_PATH" description="WF_PARAM_EDITOR_PATH_DESC" showon="statusbar_location:top[OR]statusbar_location:bottom">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
<field name="resizing" type="list" default="1" label="WF_PARAM_EDITOR_RESIZING" description="WF_PARAM_EDITOR_RESIZING_DESC" showon="statusbar_location:top[OR]statusbar_location:bottom">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
<field name="resize_horizontal" type="yesno" default="1" label="WF_PARAM_EDITOR_RESIZE_HORIZONTAL" description="WF_PARAM_EDITOR_RESIZE_HORIZONTAL_DESC" showon="resizing:1">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
<field name="active_tab" type="list" default="wysiwyg" label="WF_PARAM_EDITOR_ACTIVE_TAB" description="WF_PARAM_EDITOR_ACTIVE_TAB_DESC">
|
||||
<option value="wysiwyg">WF_PARAM_EDITOR_ACTIVE_TAB_WYSIWYG</option>
|
||||
<option value="source">WF_PARAM_EDITOR_ACTIVE_TAB_CODE</option>
|
||||
<option value="preview">WF_PARAM_EDITOR_ACTIVE_TAB_PREVIEW</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
<fieldset name="editor.setup">
|
||||
<field name="convert_urls" type="list" default="relative" label="WF_PARAM_EDITOR_CONVERT_URLS" description="WF_PARAM_EDITOR_CONVERT_URLS_DESC">
|
||||
<option value="none">WF_OPTION_NONE</option>
|
||||
<option value="relative">WF_OPTION_RELATIVE</option>
|
||||
<option value="absolute">WF_OPTION_ABSOLUTE</option>
|
||||
</field>
|
||||
<field name="verify_html" type="list" default="" label="WF_PARAM_CLEANUP" description="WF_PARAM_EDITOR_PROFILE_CLEANUP_DESC" class="btn-group btn-group-yesno">
|
||||
<option value="">WF_OPTION_INHERIT</option>
|
||||
<option value="0">JNO</option>
|
||||
<option value="1">JYES</option>
|
||||
</field>
|
||||
<field name="schema" type="list" default="" label="WF_PARAM_DOCTYPE" description="WF_PARAM_EDITOR_PROFILE_DOCTYPE_DESC">
|
||||
<option value="">WF_OPTION_INHERIT</option>
|
||||
<option value="mixed">WF_PARAM_DOCTYPE_MIXED</option>
|
||||
<option value="html4">HTML4</option>
|
||||
<option value="html5">HTML5</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
<fieldset name="editor.typography">
|
||||
<field name="forced_root_block" type="list" default="" label="WF_PARAM_ROOT_BLOCK" description="WF_PARAM_EDITOR_PROFILE_ROOT_BLOCK_DESC">
|
||||
<option value="">WF_OPTION_INHERIT</option>
|
||||
|
||||
<option value="p">WF_OPTION_PARAGRAPH</option>
|
||||
<option value="div">WF_OPTION_DIV</option>
|
||||
<option value="forced_root_block:p|force_block_newlines:0">WF_OPTION_PARAGRAPH_LINEBREAK</option>
|
||||
<option value="forced_root_block:div|force_block_newlines:0">WF_OPTION_DIV_LINEBREAK</option>
|
||||
<option value="forced_root_block:0|force_block_newlines:1">WF_OPTION_PARAGRAPH_MIXED</option>
|
||||
<option value="0">WF_OPTION_LINEBREAK</option>
|
||||
</field>
|
||||
<field name="profile_content_css" type="list" default="2" label="WF_PARAM_EDITOR_PROFILE_CSS" description="WF_PARAM_EDITOR_PROFILE_CSS_DESC">
|
||||
<option value="0">WF_PARAM_CSS_ADD</option>
|
||||
<option value="1">WF_PARAM_CSS_OVERWRITE</option>
|
||||
<option value="2">WF_PARAM_CSS_INHERIT</option>
|
||||
</field>
|
||||
|
||||
<field name="profile_content_css_custom" type="repeatable" default="" label="WF_PARAM_CSS_CUSTOM" description="WF_PARAM_CSS_CUSTOM_DESC" showon="profile_content_css:0[OR]profile_content_css:1">
|
||||
<field type="text" size="50" hiddenLabel="true" hint="eg: templates/$template/css/content.css" />
|
||||
</field>
|
||||
|
||||
<field name="custom_colors" type="textarea" rows="3" cols="50" default="" label="WF_PARAM_CUSTOM_COLORS" description="WF_PARAM_CUSTOM_COLORS_DESC" placeholder="eg: #CC0000,#FF0000" />
|
||||
</fieldset>
|
||||
<fieldset name="editor.filesystem">
|
||||
<field name="dir" type="text" default="" size="50" placeholder="images" label="WF_PARAM_DIRECTORY" description="WF_PARAM_DIRECTORY_DESC"/>
|
||||
|
||||
<field name="dir_filter" type="repeatable" default="" label="WF_PARAM_DIRECTORY_FILTER" description="WF_PARAM_DIRECTORY_FILTER_DESC">
|
||||
<field type="text" size="50" hiddenLabel="true" />
|
||||
</field>
|
||||
|
||||
<field name="filesystem" type="filesystem" default="joomla" label="WF_PARAM_FILESYSTEM" description="WF_PARAM_FILESYSTEM_DESC" />
|
||||
|
||||
<field name="max_size" class="input-small" hint="1024" max="" type="uploadmaxsize" step="128" default="" label="WF_PARAM_UPLOAD_SIZE" description="WF_PARAM_UPLOAD_SIZE_DESC" />
|
||||
|
||||
<field name="upload_conflict" type="list" default="overwrite" label="WF_PARAM_UPLOAD_EXISTS" description="WF_PARAM_UPLOAD_EXISTS_DESC">
|
||||
<option value="unique">WF_PARAM_UPLOAD_EXISTS_UNIQUE</option>
|
||||
<option value="overwrite">WF_PARAM_UPLOAD_EXISTS_OVERWRITE</option>
|
||||
</field>
|
||||
|
||||
<field name="upload_suffix" placeholder="_copy" max="" type="text" default="" label="WF_PARAM_UPLOAD_SUFFIX" description="WF_PARAM_UPLOAD_SUFFIX_DESC" showon="upload_conflict:unique" />
|
||||
|
||||
<field name="browser_position" type="list" default="bottom" label="WF_PARAM_BROWSER_POSITION" description="WF_PARAM_BROWSER_POSITION_DESC">
|
||||
<option value="top">WF_LABEL_TOP</option>
|
||||
<option value="bottom">WF_LABEL_BOTTOM</option>
|
||||
</field>
|
||||
|
||||
<field name="folder_tree" type="yesno" default="1" label="WF_PARAM_FOLDER_TREE" description="WF_PARAM_FOLDER_TREE_DESC">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
<field name="list_limit" type="list" default="all" label="WF_PARAM_LIST_LIMIT" description="WF_PARAM_LIST_LIMIT_DESC">
|
||||
<option value="10">10</option>
|
||||
<option value="25">25</option>
|
||||
<option value="50">50</option>
|
||||
<option value="100">100</option>
|
||||
<option value="all">WF_OPTION_ALL</option>
|
||||
</field>
|
||||
<field name="validate_mimetype" type="yesno" default="1" label="WF_PARAM_VALIDATE_MIMETYPE" description="WF_PARAM_VALIDATE_MIMETYPE_DESC">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
<field name="websafe_mode" type="list" default="utf-8" label="WF_PARAM_WEBSAFE_MODE" description="WF_PARAM_WEBSAFE_MODE_DESC">
|
||||
<option value="utf-8">UTF-8</option>
|
||||
<option value="ascii">ASCII</option>
|
||||
</field>
|
||||
<field name="websafe_allow_spaces" type="list" default="_" label="WF_PARAM_WEBSAFE_ALLOW_SPACES" description="WF_PARAM_WEBSAFE_ALLOW_SPACES_DESC">
|
||||
<option value="1">JYES</option>
|
||||
<option value="_">WF_OPTION_WEBSAFE_ALLOW_SPACES_UNDERSCORE</option>
|
||||
<option value="-">WF_OPTION_WEBSAFE_ALLOW_SPACES_DASH</option>
|
||||
<option value=".">WF_OPTION_WEBSAFE_ALLOW_SPACES_PERIOD</option>
|
||||
</field>
|
||||
<field name="websafe_textcase" type="checkboxes" multiple="multiple" default="uppercase,lowercase" label="WF_PARAM_WEBSAFE_TEXTCASE" description="WF_PARAM_WEBSAFE_TEXTCASE_DESC">
|
||||
<option value="uppercase">WF_OPTION_UPPERCASE</option>
|
||||
<option value="lowercase">WF_OPTION_LOWERCASE</option>
|
||||
</field>
|
||||
<field name="upload_add_random" type="yesno" default="0" label="WF_PARAM_UPLOAD_ADD_RANDOM" description="WF_PARAM_UPLOAD_ADD_RANDOM_DESC">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
<field name="date_format" type="text" default="" hint="eg: %d/%m/%Y, %H:%M" label="WF_PARAM_DATE_FORMAT" description="WF_PARAM_DATE_FORMAT_DESC" />
|
||||
<field name="total_files" type="number" default="" class="input-small" step="1" label="WF_PARAM_TOTAL_FILES_LIMIT" description="WF_PARAM_TOTAL_FILES_LIMIT_DESC" />
|
||||
<field name="total_size" type="number" default="" class="input-small" step="1" label="WF_PARAM_TOTAL_FILES_SIZE_LIMIT" description="WF_PARAM_TOTAL_FILES_SIZE_LIMIT_DESC" />
|
||||
</fieldset>
|
||||
|
||||
<fieldset name="editor.advanced">
|
||||
<field type="container" label="WF_PARAM_STARTUP_CONTENT" description="WF_PARAM_STARTUP_CONTENT_DESC">
|
||||
<field type="mediajce" name="startup_content_url" size="30" mediatype="html,htm,txt,md" default="" label="WF_PARAM_STARTUP_CONTENT_URL" description="WF_PARAM_STARTUP_CONTENT_URL_DESC" />
|
||||
|
||||
<field type="spacer" label="WF_LABEL_OR" />
|
||||
|
||||
<field type="textarea" name="startup_content_html" filter="html" rows="2" cols="3" class="input-xlarge" default="" label="WF_PARAM_STARTUP_CONTENT_HTML" spellcheck="false" description="WF_PARAM_STARTUP_CONTENT_HTML_DESC" />
|
||||
</field>
|
||||
|
||||
<field type="spacer" />
|
||||
|
||||
<field name="invalid_elements" type="text" size="50" default="" label="WF_PARAM_NO_ELEMENTS" description="WF_PARAM_NO_ELEMENTS_DESC" />
|
||||
<field name="invalid_attributes" type="text" size="50" default="dynsrc,lowsrc" label="WF_PARAM_INVALID_ATTRIBUTES" description="WF_PARAM_INVALID_ATTRIBUTES_DESC" />
|
||||
<field name="invalid_attribute_values" type="text" size="50" default="" label="WF_PARAM_INVALID_ATTRIBUTE_VALUES" description="WF_PARAM_INVALID_ATTRIBUTE_VALUES_DESC" />
|
||||
<field name="extended_elements" type="textarea" rows="2" cols="46" default="" label="WF_PARAM_ELEMENTS" description="WF_PARAM_ELEMENTS_DESC" />
|
||||
|
||||
<field name="validate_styles" type="yesno" default="1" label="WF_PARAM_VALIDATE_STYLES" description="WF_PARAM_VALIDATE_STYLES_DESC">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
|
||||
<field type="container" class="alert alert-warning p-4 bg-light" label="WF_PARAM_CODE_BLOCKS" description="WF_PARAM_CODE_BLOCKS_DESC_WARNING">
|
||||
|
||||
<field name="code_blocks" type="yesno" default="1" label="WF_PARAM_CODE_BLOCKS_ENABLE" description="WF_PARAM_CODE_BLOCKS_ENABLE_DESC">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
|
||||
<field name="allow_javascript" type="yesno" default="0" label="WF_PARAM_JAVASCRIPT" description="WF_PARAM_JAVASCRIPT_DESC">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
|
||||
<field name="allow_css" type="yesno" default="0" label="WF_PARAM_CSS" description="WF_PARAM_CSS_DESC">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
|
||||
<field name="allow_php" type="yesno" default="0" label="WF_PARAM_PHP" description="WF_PARAM_PHP_DESC">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
|
||||
<field name="allow_custom_xml" type="yesno" default="0" label="WF_PARAM_ALLOW_CUSTOM_XML" description="WF_PARAM_ALLOW_CUSTOM_XML_DESC">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
</field>
|
||||
|
||||
<field name="protect_shortcode" type="yesno" default="0" label="WF_PARAM_PROTECT_SHORTCODE" description="WF_PARAM_PROTECT_SHORTCODE_DESC">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
|
||||
<field name="allow_event_attributes" type="yesno" default="0" label="WF_PARAM_ALLOW_EVENT_ATTRIBUTES" description="WF_PARAM_ALLOW_EVENT_ATTRIBUTES_DESC" showon="allow_javascript:0">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
|
||||
<field type="spacer" hr="true" />
|
||||
<field name="wordcount_limit" type="number" default="0" label="WF_PARAM_WORDCOUNT_LIMIT" description="WF_PARAM_WORDCOUNT_LIMIT_DESC" class="input-small" />
|
||||
<field name="wordcount_alert" type="yesno" default="0" label="WF_PARAM_WORDCOUNT_ALERT" description="WF_PARAM_WORDCOUNT_ALERT_DESC">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
|
||||
<field type="spacer" hr="true" />
|
||||
<field name="object_resizing" type="yesno" default="1" label="WF_PARAM_OBJECT_RESIZING" description="WF_PARAM_OBJECT_RESIZING_DESC">
|
||||
<option value="1">JYES</option>
|
||||
<option value="0">JNO</option>
|
||||
</field>
|
||||
</fieldset>
|
||||
</fields>
|
||||
</form>
|
||||
@@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<form>
|
||||
<fieldset addfieldpath="/administrator/components/com_jce/models/fields" />
|
||||
|
||||
<fields name="filter">
|
||||
<field
|
||||
name="search"
|
||||
type="text"
|
||||
label="COM_PLUGINS_FILTER_SEARCH_LABEL"
|
||||
description="COM_PLUGINS_SEARCH_IN_TITLE"
|
||||
hint="JSEARCH_FILTER"
|
||||
/>
|
||||
|
||||
<field
|
||||
name="published"
|
||||
type="status"
|
||||
label="JOPTION_SELECT_PUBLISHED"
|
||||
description="JOPTION_SELECT_PUBLISHED_DESC"
|
||||
onchange="this.form.submit();"
|
||||
filter="0,1"
|
||||
>
|
||||
<option value="">JOPTION_SELECT_PUBLISHED</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="area"
|
||||
type="list"
|
||||
label="WF_PROFILES_AREA"
|
||||
description="WF_PROFILES_AREA_DESC"
|
||||
onchange="this.form.submit();"
|
||||
>
|
||||
<option value="">WF_PROFILES_AREA_FILTER_SELECT</option>
|
||||
<option value="1">WF_PROFILES_AREA_FRONTEND</option>
|
||||
<option value="2">WF_PROFILES_AREA_BACKEND</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="device"
|
||||
type="list"
|
||||
label="WF_PROFILES_DEVICE"
|
||||
description="WF_PROFILES_DEVICE_DESC"
|
||||
onchange="this.form.submit();"
|
||||
>
|
||||
<option value="">WF_PROFILES_DEVICE_FILTER_SELECT</option>
|
||||
<option value="phone">WF_PROFILES_DEVICE_PHONE</option>
|
||||
<option value="tablet">WF_PROFILES_DEVICE_TABLET</option>
|
||||
<option value="desktop">WF_PROFILES_DEVICE_DESKTOP</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="components"
|
||||
type="components"
|
||||
label="WF_PROFILES_COMPONENTS"
|
||||
description="WF_PROFILES_COMPONENTS_DESC"
|
||||
onchange="this.form.submit();"
|
||||
>
|
||||
<option value="">WF_PROFILES_COMPONENTS_FILTER_SELECT</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="usergroups"
|
||||
type="usergrouplist"
|
||||
label="WF_PROFILES_GROUPS"
|
||||
description="WF_PROFILES_GROUPS_DESC"
|
||||
onchange="this.form.submit();"
|
||||
>
|
||||
<option value="">WF_PROFILES_GROUPS_FILTER_SELECT</option>
|
||||
</field>
|
||||
|
||||
</fields>
|
||||
|
||||
<fields name="list">
|
||||
<field
|
||||
name="fullordering"
|
||||
type="list"
|
||||
label="JGLOBAL_SORT_BY"
|
||||
description="JGLOBAL_SORT_BY"
|
||||
onchange="this.form.submit();"
|
||||
default="folder ASC"
|
||||
>
|
||||
<option value="">JGLOBAL_SORT_BY</option>
|
||||
<option value="ordering ASC">JGRID_HEADING_ORDERING_ASC</option>
|
||||
<option value="ordering DESC">JGRID_HEADING_ORDERING_DESC</option>
|
||||
<option value="published ASC">JSTATUS_ASC</option>
|
||||
<option value="published DESC">JSTATUS_DESC</option>
|
||||
<option value="name ASC">JGLOBAL_TITLE_ASC</option>
|
||||
<option value="name DESC">JGLOBAL_TITLE_DESC</option>
|
||||
<option value="id ASC">JGRID_HEADING_ID_ASC</option>
|
||||
<option value="id DESC">JGRID_HEADING_ID_DESC</option>
|
||||
</field>
|
||||
|
||||
<field
|
||||
name="limit"
|
||||
type="limitbox"
|
||||
class="input-mini"
|
||||
default="25"
|
||||
onchange="this.form.submit();"
|
||||
/>
|
||||
</fields>
|
||||
</form>
|
||||
43
administrator/components/com_jce/models/forms/profile.xml
Normal file
43
administrator/components/com_jce/models/forms/profile.xml
Normal file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<form>
|
||||
<fields>
|
||||
<fieldset name="setup">
|
||||
<field name="name" type="text" class="input-xxlarge input-large-text" size="40" label="JGLOBAL_TITLE" description="WF_PROFILES_NAME_DESC" required="true" />
|
||||
|
||||
<field name="description" type="text" class="input-xxlarge" label="JGLOBAL_DESCRIPTION" description="WF_PROFILES_DESCRIPTION_DESC" />
|
||||
|
||||
<field name="published" type="radio" label="JSTATUS" description="WF_PROFILES_ENABLED_DESC" class="btn-group btn-group-yesno" default="1">
|
||||
<option value="1">JPUBLISHED</option>
|
||||
<option value="0">JUNPUBLISHED</option>
|
||||
</field>
|
||||
|
||||
<field name="ordering" type="Profileordering" label="JFIELD_ORDERING_LABEL" description="JFIELD_ORDERING_DESC"/>
|
||||
|
||||
<field name="id" type="hidden" default="0" />
|
||||
</fieldset>
|
||||
<fieldset name="assignment" addfieldpath="/administrator/components/com_categories/models/fields">
|
||||
<field name="area" type="checkboxes" multiple="multiple" class="inline" label="WF_PROFILES_AREA" description="WF_PROFILES_AREA_DESC" checked="1,2">
|
||||
<option value="1">WF_PROFILES_AREA_FRONTEND</option>
|
||||
<option value="2">WF_PROFILES_AREA_BACKEND</option>
|
||||
</field>
|
||||
|
||||
<field name="device" type="checkboxes" multiple="multiple" class="inline" label="WF_PROFILES_DEVICE" description="WF_PROFILES_DEVICE_DESC" checked="desktop,tablet,phone">
|
||||
<option value="phone">WF_PROFILES_DEVICE_PHONE</option>
|
||||
<option value="tablet">WF_PROFILES_DEVICE_TABLET</option>
|
||||
<option value="desktop">WF_PROFILES_DEVICE_DESKTOP</option>
|
||||
</field>
|
||||
|
||||
<field name="components_select" type="radio" label="WF_PROFILES_COMPONENTS" description="WF_PROFILES_COMPONENTS_DESC" class="extensions-select" default="0">
|
||||
<option value="0">WF_PROFILES_COMPONENTS_ALL</option>
|
||||
<option value="1">WF_PROFILES_COMPONENTS_SELECT</option>
|
||||
</field>
|
||||
|
||||
<field name="components" type="components" multiple="multiple" label="" layout="joomla.form.field.list-fancy-select" />
|
||||
|
||||
<field name="types" type="usergrouplist" multiple="multiple" label="WF_PROFILES_GROUPS" description="WF_PROFILES_GROUPS_DESC" layout="joomla.form.field.list-fancy-select" />
|
||||
<field name="users" type="users" multiple="multiple" label="WF_PROFILES_USERS" description="WF_PROFILES_USERS_DESC" />
|
||||
|
||||
</fieldset>
|
||||
</fields>
|
||||
<fields name="config"></fields>
|
||||
</form>
|
||||
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<form>
|
||||
<fields>
|
||||
<fieldset>
|
||||
|
||||
<field name="title" type="text" default="" hint="WF_STYLEFORMAT_TITLE" label="" hiddenLabel="true" />
|
||||
|
||||
<field name="element" type="groupedlist" default="" label="WF_STYLEFORMAT_ELEMENT" description="WF_STYLEFORMAT_ELEMENT_DESC">
|
||||
<option value="" selected="selected">WF_OPTION_SELECTED_ELEMENT</option>
|
||||
<group label="WF_OPTION_SECTION_ELEMENTS">
|
||||
<option value="section">section</option>
|
||||
<option value="nav">nav</option>
|
||||
<option value="article">article</option>
|
||||
<option value="aside">aside</option>
|
||||
<option value="h1">h1</option>
|
||||
<option value="h2">h2</option>
|
||||
<option value="h3">h3</option>
|
||||
<option value="h4">h4</option>
|
||||
<option value="h5">h5</option>
|
||||
<option value="h6">h6</option>
|
||||
<option value="header">header</option>
|
||||
<option value="footer">footer</option>
|
||||
<option value="address">address</option>
|
||||
<option value="main">main</option>
|
||||
</group>
|
||||
<group label="WF_OPTION_GROUPING_ELEMENTS">
|
||||
<option value="p">p</option>
|
||||
<option value="pre">pre</option>
|
||||
<option value="blockquote">blockquote</option>
|
||||
<option value="figure">figure</option>
|
||||
<option value="figcaption">figcaption</option>
|
||||
<option value="div">div</option>
|
||||
</group>
|
||||
<group label="WF_OPTION_TEXT_LEVEL_ELEMENTS">
|
||||
<option value="a">a</option>
|
||||
<option value="em">em</option>
|
||||
<option value="strong">strong</option>
|
||||
<option value="small">small</option>
|
||||
<option value="s">s</option>
|
||||
<option value="cite">cite</option>
|
||||
<option value="q">q</option>
|
||||
<option value="dfn">dfn</option>
|
||||
<option value="abbr">abbr</option>
|
||||
<option value="data">data</option>
|
||||
<option value="time">time</option>
|
||||
<option value="code">code</option>
|
||||
<option value="var">var</option>
|
||||
<option value="samp">samp</option>
|
||||
<option value="kbd">kbd</option>
|
||||
<option value="sub">sub</option>
|
||||
<option value="i">i</option>
|
||||
<option value="b">b</option>
|
||||
<option value="u">u</option>
|
||||
<option value="mark">mark</option>
|
||||
<option value="ruby">ruby</option>
|
||||
<option value="rt">rt</option>
|
||||
<option value="rp">rp</option>
|
||||
<option value="bdi">bdi</option>
|
||||
<option value="bdo">bdo</option>
|
||||
<option value="span">span</option>
|
||||
<option value="wbr">wbr</option>
|
||||
</group>
|
||||
<group label="WF_OPTION_FORM_ELEMENTS">
|
||||
<option value="form">form</option>
|
||||
<option value="input">input</option>
|
||||
<option value="button">button</option>
|
||||
<option value="fieldset">fieldset</option>
|
||||
<option value="legend">legend</option>
|
||||
</group>
|
||||
</field>
|
||||
|
||||
<field name="styles" type="text" default="" label="WF_STYLEFORMAT_STYLES" description="WF_STYLEFORMAT_STYLES_DESC" />
|
||||
<field name="attributes" type="text" default="" label="WF_STYLEFORMAT_ATTRIBUTES" description="WF_STYLEFORMAT_ATTRIBUTES_DESC" />
|
||||
<field name="selector" type="text" default="" label="WF_STYLEFORMAT_SELECTOR" description="WF_STYLEFORMAT_SELECTOR_DESC" />
|
||||
<field name="classes" type="text" default="" label="WF_STYLEFORMAT_CLASSES" description="WF_STYLEFORMAT_CLASSES_DESC" />
|
||||
|
||||
</fieldset>
|
||||
|
||||
</fields>
|
||||
</form>
|
||||
138
administrator/components/com_jce/models/help.php
Normal file
138
administrator/components/com_jce/models/help.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?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 JceModelHelp extends JModelLegacy
|
||||
{
|
||||
public function getLanguage()
|
||||
{
|
||||
$language = JFactory::getLanguage();
|
||||
$tag = $language->getTag();
|
||||
|
||||
return substr($tag, 0, strpos($tag, '-'));
|
||||
}
|
||||
|
||||
public function getTopics($file)
|
||||
{
|
||||
$result = '';
|
||||
|
||||
if (file_exists($file)) {
|
||||
// load xml
|
||||
$xml = simplexml_load_file($file);
|
||||
|
||||
if ($xml) {
|
||||
foreach ($xml->help->children() as $topic) {
|
||||
$subtopics = $topic->subtopic;
|
||||
$class = count($subtopics) ? 'subtopics' : '';
|
||||
|
||||
$key = (string) $topic->attributes()->key;
|
||||
$title = (string) $topic->attributes()->title;
|
||||
$file = (string) $topic->attributes()->file;
|
||||
|
||||
// if file attribute load file
|
||||
if ($file) {
|
||||
$result .= $this->getTopics(JPATH_SITE . '/components/com_jce/editor/' . $file);
|
||||
} else {
|
||||
$result .= '<li id="' . $key . '" class="nav-item ' . $class . '"><a href="#" class="nav-link"><i class="icon-copy"></i> ' . trim(JText::_($title)) . '</a>';
|
||||
}
|
||||
|
||||
if (count($subtopics)) {
|
||||
$result .= '<ul class="nav nav-list hidden">';
|
||||
foreach ($subtopics as $subtopic) {
|
||||
$sub_subtopics = $subtopic->subtopic;
|
||||
|
||||
// if a file is set load it as sub-subtopics
|
||||
if ($file = (string) $subtopic->attributes()->file) {
|
||||
$result .= '<li class="nav-item subtopics"><a href="#" class="nav-link"><i class="icon-file"></i> ' . trim(JText::_((string) $subtopic->attributes()->title)) . '</a>';
|
||||
$result .= '<ul class="nav nav-list hidden">';
|
||||
$result .= $this->getTopics(JPATH_SITE . '/components/com_jce/editor/' . $file);
|
||||
$result .= '</ul>';
|
||||
$result .= '</li>';
|
||||
} else {
|
||||
$id = $subtopic->attributes()->key ? ' id="' . (string) $subtopic->attributes()->key . '"' : '';
|
||||
|
||||
$class = count($sub_subtopics) ? ' class="nav-item subtopics"' : '';
|
||||
$result .= '<li' . $class . $id . '><a href="#" class="nav-link"><i class="icon-file"></i> ' . trim(JText::_((string) $subtopic->attributes()->title)) . '</a>';
|
||||
|
||||
if (count($sub_subtopics)) {
|
||||
$result .= '<ul class="nav nav-list hidden">';
|
||||
foreach ($sub_subtopics as $sub_subtopic) {
|
||||
$result .= '<li id="' . (string) $sub_subtopic->attributes()->key . '" class="nav-item"><a href="#" class="nav-link"><i class="icon-file"></i> ' . trim(JText::_((string) $sub_subtopic->attributes()->title)) . '</a></li>';
|
||||
}
|
||||
$result .= '</ul>';
|
||||
}
|
||||
|
||||
$result .= '</li>';
|
||||
}
|
||||
}
|
||||
$result .= '</ul>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a formatted list of help topics.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
public function renderTopics()
|
||||
{
|
||||
$app = JFactory::getApplication();
|
||||
|
||||
$section = $app->input->getWord('section', 'admin');
|
||||
$category = $app->input->getWord('category', 'cpanel');
|
||||
|
||||
$document = JFactory::getDocument();
|
||||
$language = JFactory::getLanguage();
|
||||
|
||||
$language->load('com_jce', JPATH_SITE);
|
||||
$language->load('com_jce_pro', JPATH_SITE);
|
||||
|
||||
$document->setTitle(JText::_('WF_HELP') . ' : ' . JText::_('WF_' . strtoupper($category) . '_TITLE'));
|
||||
|
||||
switch ($section) {
|
||||
case 'admin':
|
||||
$file = __DIR__ . '/' . $category . '.xml';
|
||||
break;
|
||||
case 'editor':
|
||||
$file = JPATH_SITE . '/components/com_jce/editor/tiny_mce/plugins/' . $category . '/' . $category . '.xml';
|
||||
|
||||
// check for installed plugin
|
||||
$plugin = JPluginHelper::getPlugin('jce', 'editor-' . $category);
|
||||
|
||||
if ($plugin) {
|
||||
$file = JPATH_PLUGINS . '/jce/editor-' . $category . '/editor-' . $category . '.xml';
|
||||
$language->load('plg_jce_editor_' . $category, JPATH_ADMINISTRATOR);
|
||||
}
|
||||
|
||||
if (!is_file($file)) {
|
||||
$file = JPATH_SITE . '/components/com_jce/editor/libraries/xml/help/editor.xml';
|
||||
} else {
|
||||
$language->load('WF_' . $category, JPATH_SITE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$result = '';
|
||||
|
||||
$result .= '<ul class="nav nav-list" id="help-menu"><li class="nav-header">' . JText::_('WF_' . strtoupper($category) . '_TITLE') . '</li>';
|
||||
$result .= $this->getTopics($file);
|
||||
$result .= '</ul>';
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
5
administrator/components/com_jce/models/help.xml
Normal file
5
administrator/components/com_jce/models/help.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<help>
|
||||
<topic key="admin.about" title="WF_HELP_ADMINISTRATION" />
|
||||
<topic key="admin.interface" title="WF_HELP_INTERFACE" />
|
||||
</help>
|
||||
164
administrator/components/com_jce/models/mediabox.php
Normal file
164
administrator/components/com_jce/models/mediabox.php
Normal file
@@ -0,0 +1,164 @@
|
||||
<?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;
|
||||
|
||||
// load base model
|
||||
jimport('joomla.application.component.modelform');
|
||||
|
||||
use Joomla\Utilities\ArrayHelper;
|
||||
|
||||
class JceModelMediabox extends JModelForm
|
||||
{
|
||||
/**
|
||||
* Returns a Table object, always creating it.
|
||||
*
|
||||
* @param type $type The table type to instantiate
|
||||
* @param string $prefix A prefix for the table class name. Optional
|
||||
* @param array $config Configuration array for model. Optional
|
||||
*
|
||||
* @return JTable A database object
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function getTable($type = 'Extension', $prefix = 'JTable', $config = array())
|
||||
{
|
||||
return JTable::getInstance($type, $prefix, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a form object.
|
||||
*
|
||||
* @param array $data Data for the form
|
||||
* @param bool $loadData True if the form is to load its own data (default case), false if not
|
||||
*
|
||||
* @return mixed A JForm object on success, false on failure
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function getForm($data = array(), $loadData = true)
|
||||
{
|
||||
JForm::addFormPath(JPATH_PLUGINS . '/system/jcemediabox');
|
||||
|
||||
JFactory::getLanguage()->load('plg_system_jcemediabox', JPATH_ADMINISTRATOR);
|
||||
JFactory::getLanguage()->load('plg_system_jcemediabox', JPATH_PLUGINS . '/system/jcemediabox');
|
||||
|
||||
// Get the form.
|
||||
$form = $this->loadForm('com_jce.mediabox', 'jcemediabox', array('control' => 'jform', 'load_data' => $loadData), true, '//config');
|
||||
|
||||
if (empty($form)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the data that should be injected in the form.
|
||||
*
|
||||
* @return mixed The data for the form
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function loadFormData()
|
||||
{
|
||||
// Check the session for previously entered form data.
|
||||
$data = JFactory::getApplication()->getUserState('com_jce.mediabox.plugin.data', array());
|
||||
|
||||
if (empty($data)) {
|
||||
$data = $this->getData();
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the configuration data.
|
||||
*
|
||||
* This method will load the global configuration data straight from
|
||||
* JConfig. If configuration data has been saved in the session, that
|
||||
* data will be merged into the original data, overwriting it.
|
||||
*
|
||||
* @return array An array containg all global config data
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
// Get the editor data
|
||||
$plugin = JPluginHelper::getPlugin('system', 'jcemediabox');
|
||||
|
||||
// json_decode
|
||||
$json = json_decode($plugin->params, true);
|
||||
|
||||
array_walk($json, function(&$value, $key) {
|
||||
if (is_numeric($value)) {
|
||||
$value = $value + 0;
|
||||
}
|
||||
});
|
||||
|
||||
$data = new StdClass;
|
||||
$data->params = $json;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to save the form data.
|
||||
*
|
||||
* @param array The form data
|
||||
*
|
||||
* @return bool True on success
|
||||
*
|
||||
* @since 2.7
|
||||
*/
|
||||
public function save($data)
|
||||
{
|
||||
$table = $this->getTable();
|
||||
|
||||
$id = $table->find(array(
|
||||
'type' => 'plugin',
|
||||
'element' => 'jcemediabox',
|
||||
'folder' => 'system'
|
||||
));
|
||||
|
||||
if (!$id) {
|
||||
$this->setError('Invalid plugin');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the previous Data
|
||||
if (!$table->load($id))
|
||||
{
|
||||
$this->setError($table->getError());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bind the data.
|
||||
if (!$table->bind($data)) {
|
||||
$this->setError($table->getError());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the data.
|
||||
if (!$table->check()) {
|
||||
$this->setError($table->getError());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store the data.
|
||||
if (!$table->store()) {
|
||||
$this->setError($table->getError());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
7
administrator/components/com_jce/models/mediabox.xml
Normal file
7
administrator/components/com_jce/models/mediabox.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<mediabox>
|
||||
<help>
|
||||
<topic key="admin.mediabox.config" title="WF_MEDIABOX_HELP_CONFIG" />
|
||||
</help>
|
||||
</mediabox>
|
||||
|
||||
904
administrator/components/com_jce/models/profile.php
Normal file
904
administrator/components/com_jce/models/profile.php
Normal file
@@ -0,0 +1,904 @@
|
||||
<?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 JPATH_SITE . '/components/com_jce/editor/libraries/classes/editor.php';
|
||||
|
||||
require JPATH_ADMINISTRATOR . '/components/com_jce/helpers/plugins.php';
|
||||
require JPATH_ADMINISTRATOR . '/components/com_jce/helpers/profiles.php';
|
||||
|
||||
/**
|
||||
* Item Model for a Profile.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
class JceModelProfile extends JModelAdmin
|
||||
{
|
||||
/**
|
||||
* The type alias for this content type.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 3.2
|
||||
*/
|
||||
public $typeAlias = 'com_jce.profile';
|
||||
|
||||
/**
|
||||
* The prefix to use with controller messages.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected $text_prefix = 'COM_JCE';
|
||||
|
||||
/**
|
||||
* Returns a Table object, always creating it.
|
||||
*
|
||||
* @param type $type The table type to instantiate
|
||||
* @param string $prefix A prefix for the table class name. Optional
|
||||
* @param array $config Configuration array for model. Optional
|
||||
*
|
||||
* @return JTable A database object
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function getTable($type = 'Profiles', $prefix = 'JceTable', $config = array())
|
||||
{
|
||||
return JTable::getInstance($type, $prefix, $config);
|
||||
}
|
||||
|
||||
/* Override to prevent plugins from processing form data */
|
||||
protected function preprocessData($context, &$data, $group = 'system')
|
||||
{
|
||||
if (!isset($data->config)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$config = $data->config;
|
||||
|
||||
if (is_string($config)) {
|
||||
$config = json_decode($config, true);
|
||||
}
|
||||
|
||||
if (empty($config)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// editor parameters
|
||||
if (isset($config['editor'])) {
|
||||
if (!empty($config['editor']['toolbar_theme']) && $config['editor']['toolbar_theme'] === 'mobile') {
|
||||
$config['editor']['toolbar_theme'] = 'default.touch';
|
||||
}
|
||||
|
||||
if (isset($config['editor']['relative_urls']) && !isset($config['editor']['convert_urls'])) {
|
||||
$config['editor']['convert_urls'] = $config['editor']['relative_urls'] == 0 ? 'absolute' : 'relative';
|
||||
}
|
||||
}
|
||||
|
||||
// decode config values for display
|
||||
array_walk_recursive($config, function(&$value) {
|
||||
$value = htmlspecialchars_decode($value);
|
||||
});
|
||||
|
||||
$data->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to allow derived classes to preprocess the form.
|
||||
*
|
||||
* @param JForm $form A JForm object
|
||||
* @param mixed $data The data expected for the form
|
||||
* @param string $group The name of the plugin group to import (defaults to "content")
|
||||
*
|
||||
* @see JFormField
|
||||
* @since 1.6
|
||||
*
|
||||
* @throws Exception if there is an error in the form event
|
||||
*/
|
||||
protected function preprocessForm(JForm $form, $data, $group = 'content')
|
||||
{
|
||||
if (!empty($data)) {
|
||||
$registry = new JRegistry($data->config);
|
||||
|
||||
// process individual fields to remove default value if required
|
||||
$fields = $form->getFieldset();
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$name = $field->getAttribute('name');
|
||||
|
||||
// get the field group and add the field name
|
||||
$group = (string) $field->group;
|
||||
|
||||
// must be a grouped parameter, eg: editor, imgmanager etc.
|
||||
if (!$group) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// create key from group and name
|
||||
$group = $group . '.' . $name;
|
||||
|
||||
// explode group to array
|
||||
$parts = explode('.', $group);
|
||||
|
||||
// remove "config" from group name so it matches params data object
|
||||
if ($parts[0] === "config") {
|
||||
array_shift($parts);
|
||||
$group = implode('.', $parts);
|
||||
}
|
||||
|
||||
// reset the "default" attribute value if a value is set
|
||||
if ($registry->exists($group)) {
|
||||
$form->setFieldAttribute($name, 'default', '', (string) $field->group);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// allow plugins to process form, eg: MediaField etc.
|
||||
parent::preprocessForm($form, $data);
|
||||
}
|
||||
|
||||
public function getForm($data = array(), $loadData = true)
|
||||
{
|
||||
JFormHelper::addFieldPath('JPATH_ADMINISTRATOR/components/com_jce/models/fields');
|
||||
|
||||
// Get the setup form.
|
||||
$form = $this->loadForm('com_jce.profile', 'profile', array('control' => 'jform', 'load_data' => false));
|
||||
|
||||
if (!$form) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JFactory::getLanguage()->load('com_jce_pro', JPATH_SITE);
|
||||
|
||||
// editor manifest
|
||||
$manifest = __DIR__ . '/forms/editor.xml';
|
||||
|
||||
// load editor manifest
|
||||
if (is_file($manifest)) {
|
||||
if ($editor_xml = simplexml_load_file($manifest)) {
|
||||
$form->setField($editor_xml, 'config');
|
||||
}
|
||||
}
|
||||
|
||||
// pro manifest
|
||||
$manifest = WF_EDITOR_LIBRARIES . '/pro/xml/pro.xml';
|
||||
|
||||
// load pro manifest
|
||||
if (is_file($manifest)) {
|
||||
if ($pro_xml = simplexml_load_file($manifest)) {
|
||||
$form->setField($pro_xml, 'config');
|
||||
}
|
||||
}
|
||||
|
||||
$data = $this->loadFormData();
|
||||
|
||||
// Allow for additional modification of the form, and events to be triggered.
|
||||
// We pass the data because plugins may require it.
|
||||
$this->preprocessForm($form, $data);
|
||||
|
||||
// Load the data into the form after the plugins have operated.
|
||||
$form->bind($data);
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get the data that should be injected in the form.
|
||||
*
|
||||
* @return mixed The data for the form
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function loadFormData()
|
||||
{
|
||||
$data = $this->getItem();
|
||||
|
||||
// convert 0 value to null to force defaults
|
||||
if (empty($data->area)) {
|
||||
$data->area = null;
|
||||
}
|
||||
|
||||
// convert to array if set
|
||||
if (!empty($data->device)) {
|
||||
$data->device = explode(',', $data->device);
|
||||
}
|
||||
|
||||
if (!empty($data->components)) {
|
||||
$data->components = explode(',', $data->components);
|
||||
$data->components_select = 1;
|
||||
}
|
||||
|
||||
$data->types = explode(',', $data->types);
|
||||
$data->config = $data->params;
|
||||
|
||||
$this->preprocessData('com_jce.profiles', $data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getRows()
|
||||
{
|
||||
$data = $this->getItem();
|
||||
|
||||
$array = array();
|
||||
$rows = explode(';', $data->rows);
|
||||
|
||||
$plugins = $this->getButtons();
|
||||
|
||||
$i = 1;
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$groups = array();
|
||||
// remove spacers
|
||||
$row = str_replace(array('|', 'spacer'), '', $row);
|
||||
|
||||
foreach (explode('spacer', $row) as $group) {
|
||||
// get items in group
|
||||
$items = explode(',', $group);
|
||||
$buttons = array();
|
||||
|
||||
// remove duplicates
|
||||
$items = array_unique($items);
|
||||
|
||||
foreach ($items as $x => $item) {
|
||||
if ($item === 'spacer') {
|
||||
unset($items[$x]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// not in the list...
|
||||
if (empty($item) || array_key_exists($item, $plugins) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// must be assigned...
|
||||
if (!$plugins[$item]->active) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// assign icon
|
||||
$buttons[] = $plugins[$item];
|
||||
}
|
||||
|
||||
$groups[] = $buttons;
|
||||
}
|
||||
|
||||
$array[$i] = $groups;
|
||||
|
||||
++$i;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of buttons not in the current editor layout.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAvailableButtons()
|
||||
{
|
||||
$plugins = $this->getButtons();
|
||||
|
||||
$available = array_filter($plugins, function ($plugin) {
|
||||
return !$plugin->active;
|
||||
});
|
||||
|
||||
return $available;
|
||||
}
|
||||
|
||||
public function getAdditionalPlugins()
|
||||
{
|
||||
$plugins = $this->getButtons();
|
||||
|
||||
$additional = array_filter($plugins, function ($plugin) {
|
||||
return $plugin->editable && !$plugin->row;
|
||||
});
|
||||
|
||||
return $additional;
|
||||
}
|
||||
|
||||
public function getButtons()
|
||||
{
|
||||
$commands = $this->getCommands();
|
||||
$plugins = $this->getPlugins();
|
||||
|
||||
return array_merge($commands, $plugins);
|
||||
}
|
||||
|
||||
public function getCommands()
|
||||
{
|
||||
static $commands;
|
||||
|
||||
if (empty($commands)) {
|
||||
$data = $this->getItem();
|
||||
$rows = preg_split('#[;,]#', $data->rows);
|
||||
|
||||
$commands = array();
|
||||
|
||||
foreach (JcePluginsHelper::getCommands() as $name => $command) {
|
||||
// set as active
|
||||
$command->active = in_array($name, $rows);
|
||||
$command->icon = explode(',', $command->icon);
|
||||
|
||||
// set default empty value
|
||||
$command->image = '';
|
||||
|
||||
// ui class, default is blank
|
||||
if (empty($command->class)) {
|
||||
$command->class = '';
|
||||
}
|
||||
|
||||
// cast row to integer
|
||||
$command->row = (int) $command->row;
|
||||
|
||||
// cast editable to integer
|
||||
$command->editable = (int) $command->editable;
|
||||
|
||||
// translate title
|
||||
$command->title = JText::_($command->title);
|
||||
|
||||
// translate description
|
||||
$command->description = JText::_($command->description);
|
||||
|
||||
$command->name = $name;
|
||||
|
||||
$commands[$name] = $command;
|
||||
}
|
||||
}
|
||||
|
||||
// merge plugins and commands
|
||||
return $commands;
|
||||
}
|
||||
|
||||
public function getPlugins()
|
||||
{
|
||||
static $plugins;
|
||||
|
||||
if (empty($plugins)) {
|
||||
$plugins = array();
|
||||
|
||||
$data = $this->loadFormData();
|
||||
|
||||
// array or profile plugin items
|
||||
$rows = explode(',', $data->plugins);
|
||||
|
||||
// remove duplicates
|
||||
$rows = array_unique($rows);
|
||||
|
||||
$extensions = JcePluginsHelper::getExtensions();
|
||||
|
||||
// only need plugins with xml files
|
||||
foreach (JcePluginsHelper::getPlugins() as $name => $plugin) {
|
||||
$plugin->icon = empty($plugin->icon) ? array() : explode(',', $plugin->icon);
|
||||
|
||||
// set as active if it is in the profile
|
||||
$plugin->active = in_array($plugin->name, $rows);
|
||||
|
||||
// ui class, default is blank
|
||||
if (empty($plugin->class)) {
|
||||
$plugin->class = '';
|
||||
}
|
||||
|
||||
$plugin->class = preg_replace_callback('#\b([a-z0-9]+)-([a-z0-9]+)\b#', function ($matches) {
|
||||
return 'mce' . ucfirst($matches[1]) . ucfirst($matches[2]);
|
||||
}, $plugin->class);
|
||||
|
||||
// translate title
|
||||
$plugin->title = JText::_($plugin->title);
|
||||
|
||||
// translate description
|
||||
$plugin->description = JText::_($plugin->description);
|
||||
|
||||
// cast row to integer
|
||||
$plugin->row = (int) $plugin->row;
|
||||
|
||||
// cast editable to integer
|
||||
$plugin->editable = (int) $plugin->editable;
|
||||
|
||||
// plugin extensions
|
||||
$plugin->extensions = array();
|
||||
|
||||
if (is_file($plugin->manifest)) {
|
||||
$plugin->form = $this->loadForm('com_jce.profile.' . $plugin->name, $plugin->manifest, array('control' => 'jform[config]', 'load_data' => true), true, '//extension');
|
||||
$plugin->formclass = 'options-grid-form options-grid-form-full';
|
||||
|
||||
$fieldsets = $plugin->form->getFieldsets();
|
||||
|
||||
// no parameter fields
|
||||
if (empty($fieldsets)) {
|
||||
$plugin->form = false;
|
||||
$plugins[$name] = $plugin;
|
||||
continue;
|
||||
}
|
||||
|
||||
// bind data to the form
|
||||
$plugin->form->bind($data->params);
|
||||
|
||||
foreach ($extensions as $type => $items) {
|
||||
|
||||
$item = new StdClass;
|
||||
$item->name = '';
|
||||
$item->title = '';
|
||||
$item->manifest = WF_EDITOR_LIBRARIES . '/xml/config/' . $type . '.xml';
|
||||
$item->context = '';
|
||||
|
||||
array_unshift($items, $item);
|
||||
|
||||
foreach ($items as $p) {
|
||||
// check for plugin fieldset using xpath, as fieldset can be empty
|
||||
$fieldset = $plugin->form->getXml()->xpath('(//fieldset[@name="plugin.' . $type . '"])');
|
||||
|
||||
// not supported, move along...
|
||||
if (empty($fieldset)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$context = (string) $fieldset[0]->attributes()->context;
|
||||
|
||||
// check for a context, eg: images, web, video
|
||||
if ($context && !in_array($p->context, explode(',', $context))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_file($p->manifest)) {
|
||||
$path = array($plugin->name, $type, $p->name);
|
||||
|
||||
// create new extension object
|
||||
$extension = new StdClass;
|
||||
|
||||
// set extension name as the plugin name
|
||||
$extension->name = $p->name;
|
||||
|
||||
// set extension title
|
||||
$extension->title = $p->title;
|
||||
|
||||
// load form
|
||||
$extension->form = $this->loadForm('com_jce.profile.' . implode('.', $path), $p->manifest, array('control' => 'jform[config][' . $plugin->name . '][' . $type . ']', 'load_data' => true), true, '//extension');
|
||||
$extension->formclass = 'options-grid-form options-grid-form-full';
|
||||
|
||||
// get fieldsets if any
|
||||
$fieldsets = $extension->form->getFieldsets();
|
||||
|
||||
foreach ($fieldsets as $fieldset) {
|
||||
// load form
|
||||
$plugin->extensions[$type][$p->name] = $extension;
|
||||
|
||||
if (!isset($data->params[$plugin->name])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($data->params[$plugin->name][$type])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// bind data to the form
|
||||
$extension->form->bind($data->params[$plugin->name][$type]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add to array
|
||||
$plugins[$name] = $plugin;
|
||||
}
|
||||
}
|
||||
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare and sanitise the table data prior to saving.
|
||||
*
|
||||
* @param JTable $table A reference to a JTable object
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function prepareTable($table)
|
||||
{
|
||||
$date = JFactory::getDate();
|
||||
$user = JFactory::getUser();
|
||||
|
||||
foreach ($table->getProperties() as $key => $value) {
|
||||
switch ($key) {
|
||||
case 'name':
|
||||
case 'description':
|
||||
$value = filter_var($value, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_LOW);
|
||||
break;
|
||||
case 'device':
|
||||
$value = implode(',', filter_var_array($value, FILTER_SANITIZE_STRING));
|
||||
break;
|
||||
case 'area':
|
||||
if (is_array($value)) {
|
||||
// remove empty value
|
||||
$value = array_filter($value, 'strlen');
|
||||
|
||||
// for simplicity, set multiple area selections as "0"
|
||||
if (count($value) > 1) {
|
||||
$value = 0;
|
||||
} else {
|
||||
$value = $value[0];
|
||||
}
|
||||
}
|
||||
|
||||
$value = $value;
|
||||
|
||||
break;
|
||||
case 'components':
|
||||
|
||||
if (is_array($value)) {
|
||||
$value = implode(',', filter_var_array($value, FILTER_SANITIZE_STRING));
|
||||
}
|
||||
|
||||
break;
|
||||
case 'types':
|
||||
case 'users':
|
||||
|
||||
if (is_string($value)) {
|
||||
$value = filter_var($value, FILTER_SANITIZE_NUMBER_INT);
|
||||
}
|
||||
|
||||
if (is_array($value)) {
|
||||
$value = implode(',', filter_var_array($value, FILTER_SANITIZE_NUMBER_INT));
|
||||
}
|
||||
|
||||
break;
|
||||
case 'plugins':
|
||||
$value = preg_replace('#[^\w,]+#', '', $value);
|
||||
break;
|
||||
case 'rows':
|
||||
$value = preg_replace('#[^\w,;]+#', '', $value);
|
||||
break;
|
||||
case 'params':
|
||||
break;
|
||||
}
|
||||
|
||||
$table->$key = $value;
|
||||
}
|
||||
|
||||
if (empty($table->id)) {
|
||||
// Set ordering to the last item if not set
|
||||
if (empty($table->ordering)) {
|
||||
$db = $this->getDbo();
|
||||
$query = $db->getQuery(true)
|
||||
->select('MAX(ordering)')
|
||||
->from($db->quoteName('#__wf_profiles'));
|
||||
|
||||
$db->setQuery($query);
|
||||
$max = $db->loadResult();
|
||||
|
||||
$table->ordering = $max + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function validate($form, $data, $group = null)
|
||||
{
|
||||
$filter = JFilterInput::getInstance();
|
||||
|
||||
// get unfiltered config data
|
||||
$config = isset($data['config']) ? $data['config'] : array();
|
||||
|
||||
// get layout rows and plugins data
|
||||
$rows = isset($data['rows']) ? $data['rows'] : '';
|
||||
$plugins = isset($data['plugins']) ? $data['plugins'] : '';
|
||||
|
||||
// clean layout rows and plugins data
|
||||
$data['rows'] = $filter->clean($rows, 'STRING');
|
||||
$data['plugins'] = $filter->clean($plugins, 'STRING');
|
||||
|
||||
// add back config data
|
||||
$data['params'] = $filter->clean($config, 'ARRAY');
|
||||
|
||||
if (empty($data['components']) || empty($data['components_select'])) {
|
||||
$data['components'] = '';
|
||||
}
|
||||
|
||||
if (empty($data['users'])) {
|
||||
$data['users'] = '';
|
||||
}
|
||||
|
||||
if (empty($data['types'])) {
|
||||
$data['types'] = '';
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private static function cleanParamData($data)
|
||||
{
|
||||
// clean up link plugin parameters
|
||||
array_walk($data, function(&$params, $plugin) {
|
||||
if ($plugin === "link") {
|
||||
if (isset($params['dir'])) {
|
||||
|
||||
if (!empty($params['dir']) && empty($params['direction'])) {
|
||||
$params['direction'] = $params['dir'];
|
||||
}
|
||||
|
||||
unset($params['dir']);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($params) && WFUtility::is_associative_array($params)) {
|
||||
array_walk($params, function(&$value, $key) {
|
||||
if (is_string($value) && WFUtility::isJson($value)) {
|
||||
$value = json_decode($value, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to save the form data.
|
||||
*
|
||||
* @param array The form data
|
||||
*
|
||||
* @return bool True on success
|
||||
*
|
||||
* @since 2.7
|
||||
*/
|
||||
public function save($data)
|
||||
{
|
||||
$app = JFactory::getApplication();
|
||||
|
||||
// get profile table
|
||||
$table = $this->getTable();
|
||||
|
||||
// Alter the title for save as copy
|
||||
if ($app->input->get('task') == 'save2copy') {
|
||||
|
||||
// Alter the title
|
||||
$name = $data['name'];
|
||||
|
||||
while ($table->load(array('name' => $name))) {
|
||||
if ($name == $table->name) {
|
||||
$name = Joomla\String\StringHelper::increment($name);
|
||||
}
|
||||
}
|
||||
|
||||
$data['name'] = $name;
|
||||
$data['published'] = 0;
|
||||
}
|
||||
|
||||
$key = $table->getKeyName();
|
||||
$pk = (!empty($data[$key])) ? $data[$key] : (int) $this->getState($this->getName() . '.id');
|
||||
|
||||
if ($pk && $table->load($pk)) {
|
||||
|
||||
if (empty($data['rows'])) {
|
||||
$data['rows'] = $table->rows;
|
||||
}
|
||||
|
||||
if (empty($data['plugins'])) {
|
||||
$data['plugins'] = $table->plugins;
|
||||
}
|
||||
|
||||
$json = array();
|
||||
$params = empty($table->params) ? '' : $table->params;
|
||||
|
||||
// convert params to json data array
|
||||
$params = (array) json_decode($params, true);
|
||||
|
||||
$plugins = isset($data['plugins']) ? $data['plugins'] : $table->plugins;
|
||||
|
||||
// get plugins
|
||||
$items = explode(',', $plugins);
|
||||
// add "editor"
|
||||
$items[] = 'editor';
|
||||
|
||||
// make sure we have a value
|
||||
if (empty($data['params'])) {
|
||||
$data['params'] = array();
|
||||
}
|
||||
|
||||
$data['params'] = self::cleanParamData($data['params']);
|
||||
|
||||
// data for editor and plugins
|
||||
foreach ($items as $item) {
|
||||
// add config data
|
||||
if (array_key_exists($item, $data['params'])) {
|
||||
$value = $data['params'][$item];
|
||||
// clean and add to json array for merging
|
||||
$json[$item] = filter_var_array($value, FILTER_SANITIZE_SPECIAL_CHARS);
|
||||
}
|
||||
}
|
||||
|
||||
// merge and encode as json string
|
||||
$data['params'] = json_encode(WFUtility::array_merge_recursive_distinct($params, $json));
|
||||
}
|
||||
|
||||
// set a default value for validation
|
||||
if (empty($data['params'])) {
|
||||
$data['params'] = '{}';
|
||||
}
|
||||
|
||||
if (parent::save($data)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function copy($ids)
|
||||
{
|
||||
// Check for request forgeries
|
||||
JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
|
||||
$table = $this->getTable();
|
||||
|
||||
foreach ($ids as $id) {
|
||||
if (!$table->load($id)) {
|
||||
$this->setError($table->getError());
|
||||
} else {
|
||||
$name = JText::sprintf('WF_PROFILES_COPY_OF', $table->name);
|
||||
$table->name = $name;
|
||||
$table->id = 0;
|
||||
$table->published = 0;
|
||||
}
|
||||
|
||||
// Check the row.
|
||||
if (!$table->check()) {
|
||||
$this->setError($table->getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store the row.
|
||||
if (!$table->store()) {
|
||||
$this->setError($table->getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function export($ids)
|
||||
{
|
||||
$db = JFactory::getDBO();
|
||||
|
||||
$buffer = '<?xml version="1.0" encoding="utf-8" standalone="yes"?>';
|
||||
$buffer .= "\n" . '<export type="profiles">';
|
||||
$buffer .= "\n\t" . '<profiles>';
|
||||
|
||||
$validFields = array('name', 'description', 'users', 'types', 'components', 'area', 'device', 'rows', 'plugins', 'published', 'ordering', 'params');
|
||||
|
||||
foreach ($ids as $id) {
|
||||
$table = $this->getTable();
|
||||
|
||||
if (!$table->load($id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$buffer .= "\n\t\t";
|
||||
$buffer .= '<profile>';
|
||||
|
||||
$fields = $table->getProperties();
|
||||
|
||||
foreach ($fields as $key => $value) {
|
||||
// only allow a subset of fields
|
||||
if (false == in_array($key, $validFields)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// set published to 0
|
||||
if ($key === "published") {
|
||||
$value = 0;
|
||||
}
|
||||
|
||||
if ($key == 'params') {
|
||||
$buffer .= "\n\t\t\t" . '<' . $key . '><![CDATA[' . trim($value) . ']]></' . $key . '>';
|
||||
} else {
|
||||
$buffer .= "\n\t\t\t" . '<' . $key . '>' . JceProfilesHelper::encodeData($value) . '</' . $key . '>';
|
||||
}
|
||||
}
|
||||
|
||||
$buffer .= "\n\t\t</profile>";
|
||||
}
|
||||
|
||||
$buffer .= "\n\t</profiles>";
|
||||
$buffer .= "\n</export>";
|
||||
|
||||
// set_time_limit doesn't work in safe mode
|
||||
if (!ini_get('safe_mode')) {
|
||||
@set_time_limit(0);
|
||||
}
|
||||
|
||||
$name = 'jce_editor_profile_' . date('Y_m_d') . '.xml';
|
||||
|
||||
$app = JFactory::getApplication();
|
||||
|
||||
$app->allowCache(false);
|
||||
$app->setHeader('Content-Transfer-Encoding', 'binary');
|
||||
$app->setHeader('Content-Type', 'text/xml');
|
||||
$app->setHeader('Content-Disposition', 'attachment;filename="' . $name . '";');
|
||||
|
||||
// set output content
|
||||
$app->setBody($buffer);
|
||||
|
||||
// stream to client
|
||||
echo $app->toString();
|
||||
|
||||
jexit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Process XML restore file.
|
||||
*
|
||||
* @param object $xml
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function import()
|
||||
{
|
||||
// Check for request forgeries
|
||||
JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN'));
|
||||
|
||||
jimport('joomla.filesystem.file');
|
||||
|
||||
$app = JFactory::getApplication();
|
||||
$tmp = $app->getCfg('tmp_path');
|
||||
|
||||
jimport('joomla.filesystem.file');
|
||||
|
||||
$file = $app->input->files->get('profile_file', null, 'raw');
|
||||
|
||||
// check for valid uploaded file
|
||||
if (empty($file) || !is_uploaded_file($file['tmp_name'])) {
|
||||
$app->enqueueMessage(JText::_('WF_PROFILES_UPLOAD_NOFILE'), 'error');
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($file['error'] || $file['size'] < 1) {
|
||||
$app->enqueueMessage(JText::_('WF_PROFILES_UPLOAD_NOFILE'), 'error');
|
||||
return false;
|
||||
}
|
||||
|
||||
// sanitize the file name
|
||||
$name = JFile::makeSafe($file['name']);
|
||||
|
||||
if (empty($name)) {
|
||||
$app->enqueueMessage(JText::_('WF_PROFILES_IMPORT_ERROR'), 'error');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Build the appropriate paths.
|
||||
$config = JFactory::getConfig();
|
||||
$destination = $config->get('tmp_path') . '/' . $name;
|
||||
$source = $file['tmp_name'];
|
||||
|
||||
// Move uploaded file.
|
||||
JFile::upload($source, $destination, false, true);
|
||||
|
||||
if (!is_file($destination)) {
|
||||
$app->enqueueMessage(JText::_('WF_PROFILES_UPLOAD_FAILED'), 'error');
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = JceProfilesHelper::processImport($destination);
|
||||
|
||||
if ($result === false) {
|
||||
$app->enqueueMessage(JText::_('WF_PROFILES_IMPORT_ERROR'), 'error');
|
||||
return false;
|
||||
}
|
||||
|
||||
$app->enqueueMessage(JText::sprintf('WF_PROFILES_IMPORT_SUCCESS', $result));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
266
administrator/components/com_jce/models/profiles.php
Normal file
266
administrator/components/com_jce/models/profiles.php
Normal file
@@ -0,0 +1,266 @@
|
||||
<?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_COMPONENT_ADMINISTRATOR . '/helpers/profiles.php';
|
||||
|
||||
class JceModelProfiles extends JModelList
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $config An optional associative array of configuration settings.
|
||||
*
|
||||
* @see JControllerLegacy
|
||||
* @since 1.6
|
||||
*/
|
||||
public function __construct($config = array())
|
||||
{
|
||||
if (empty($config['filter_fields'])) {
|
||||
$config['filter_fields'] = array(
|
||||
'id', 'id',
|
||||
'name', 'name',
|
||||
'checked_out', 'checked_out',
|
||||
'checked_out_time', 'checked_out_time',
|
||||
'published', 'published',
|
||||
'ordering', 'ordering'
|
||||
);
|
||||
}
|
||||
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to auto-populate the model state.
|
||||
*
|
||||
* @param string $ordering An optional ordering field.
|
||||
* @param string $direction An optional direction (asc|desc).
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @note Calling getState in this method will result in recursion.
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function populateState($ordering = 'id', $direction = 'asc')
|
||||
{
|
||||
// Load the filter state.
|
||||
$this->setState('filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search', '', 'string'));
|
||||
|
||||
// Load the parameters.
|
||||
$params = JComponentHelper::getParams('com_jce');
|
||||
$this->setState('params', $params);
|
||||
|
||||
// List state information.
|
||||
parent::populateState($ordering, $direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get a store id based on model configuration state.
|
||||
*
|
||||
* This is necessary because the model is used by the component and
|
||||
* different modules that might need different sets of data or different
|
||||
* ordering requirements.
|
||||
*
|
||||
* @param string $id A prefix for the store id.
|
||||
*
|
||||
* @return string A store id.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function getStoreId($id = '')
|
||||
{
|
||||
// Compile the store id.
|
||||
$id .= ':' . $this->getState('filter.search');
|
||||
$id .= ':' . $this->getState('filter.published');
|
||||
$id .= ':' . $this->getState('filter.components');
|
||||
|
||||
return parent::getStoreId($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to get an array of data items.
|
||||
*
|
||||
* @return mixed An array of data items on success, false on failure.
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
public function getItems()
|
||||
{
|
||||
$items = parent::getItems();
|
||||
|
||||
// Filter by device
|
||||
$device = $this->getState('filter.device');
|
||||
|
||||
// Filter by component
|
||||
$components = $this->getState('filter.components');
|
||||
|
||||
// Filter by user groups
|
||||
$usergroups = $this->getState('filter.usergroups');
|
||||
|
||||
$items = array_filter($items, function($item) use ($device, $components, $usergroups) {
|
||||
$state = true;
|
||||
|
||||
if ($device) {
|
||||
$state = in_array($device, explode(',', $item->device));
|
||||
}
|
||||
|
||||
if ($components) {
|
||||
$state = in_array($components, explode(',', $item->components));
|
||||
}
|
||||
|
||||
if ($usergroups) {
|
||||
$state = in_array($usergroups, explode(',', $item->types));
|
||||
}
|
||||
|
||||
return $state;
|
||||
});
|
||||
|
||||
// Get a storage key.
|
||||
$store = $this->getStoreId();
|
||||
|
||||
// update cache store
|
||||
$this->cache[$store] = $items;
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an SQL query to load the list data.
|
||||
*
|
||||
* @return JDatabaseQuery
|
||||
*
|
||||
* @since 1.6
|
||||
*/
|
||||
protected function getListQuery()
|
||||
{
|
||||
// Create a new query object.
|
||||
$db = $this->getDbo();
|
||||
$query = $db->getQuery(true);
|
||||
$user = JFactory::getUser();
|
||||
|
||||
// Select the required fields from the table.
|
||||
$query->select(
|
||||
$this->getState(
|
||||
'list.select',
|
||||
'*'
|
||||
)
|
||||
);
|
||||
|
||||
$query->from($db->quoteName('#__wf_profiles'));
|
||||
|
||||
// Filter by published state
|
||||
$published = $this->getState('filter.published');
|
||||
|
||||
if (is_numeric($published))
|
||||
{
|
||||
$query->where($db->quoteName('published') . ' = ' . (int) $published);
|
||||
}
|
||||
elseif ($published === '')
|
||||
{
|
||||
$query->where('(' . $db->quoteName('published') . ' = 0 OR ' . $db->quoteName('published') . ' = 1)');
|
||||
}
|
||||
|
||||
// Filter by area
|
||||
$area = (int) $this->getState('filter.area');
|
||||
|
||||
if ($area)
|
||||
{
|
||||
$query->where($db->quoteName('area') . ' = ' . (int) $area);
|
||||
}
|
||||
|
||||
// Filter by search in title
|
||||
$search = $this->getState('filter.search');
|
||||
|
||||
if (!empty($search)) {
|
||||
if (stripos($search, 'id:') === 0) {
|
||||
$query->where($db->quoteName('id') . ' = ' . (int) substr($search, 3));
|
||||
} else {
|
||||
$search = $db->quote('%' . str_replace(' ', '%', $db->escape(trim($search), true) . '%'));
|
||||
$query->where('(' . $db->quoteName('name') . ' LIKE ' . $search . ' OR ' . $db->quoteName('description') . ' LIKE ' . $search . ')');
|
||||
}
|
||||
}
|
||||
|
||||
// Add the list ordering clause.
|
||||
$listOrder = $this->getState('list.ordering', 'ordering');
|
||||
$listDirn = $this->getState('list.direction', 'ASC');
|
||||
|
||||
$query->order($db->escape($listOrder . ' ' . $listDirn));
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function repair()
|
||||
{
|
||||
$file = __DIR__ . '/profiles.xml';
|
||||
|
||||
if (!is_file($file)) {
|
||||
$this->setError(JText::_('WF_PROFILES_REPAIR_ERROR'));
|
||||
return false;
|
||||
}
|
||||
|
||||
$xml = simplexml_load_file($file);
|
||||
|
||||
if (!$xml) {
|
||||
$this->setError(JText::_('WF_PROFILES_REPAIR_ERROR'));
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($xml->profiles->children() as $profile) {
|
||||
$groups = JceProfilesHelper::getUserGroups((int) $profile->children('area'));
|
||||
|
||||
$table = JTable::getInstance('Profiles', 'JceTable');
|
||||
|
||||
foreach ($profile->children() as $item) {
|
||||
switch ((string) $item->getName()) {
|
||||
case 'description':
|
||||
$table->description = JText::_((string) $item);
|
||||
case 'types':
|
||||
$table->types = implode(',', $groups);
|
||||
break;
|
||||
case 'area':
|
||||
$table->area = (int) $item;
|
||||
break;
|
||||
case 'rows':
|
||||
$table->rows = (string) $item;
|
||||
break;
|
||||
case 'plugins':
|
||||
$table->plugins = (string) $item;
|
||||
break;
|
||||
default:
|
||||
$key = $item->getName();
|
||||
$table->$key = (string) $item;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// default
|
||||
$table->checked_out = 0;
|
||||
$table->checked_out_time = '0000-00-00 00:00:00';
|
||||
|
||||
// Check the data.
|
||||
if (!$table->check()) {
|
||||
$this->setError($table->getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store the data.
|
||||
if (!$table->store()) {
|
||||
$this->setError($table->getError());
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
93
administrator/components/com_jce/models/profiles.xml
Normal file
93
administrator/components/com_jce/models/profiles.xml
Normal file
@@ -0,0 +1,93 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<profiles>
|
||||
<help>
|
||||
<topic key="admin.profiles.about" title="WF_PROFILES_HELP_ABOUT" />
|
||||
<topic key="admin.profiles.manage" title="WF_PROFILES_HELP_MANAGE">
|
||||
<subtopic key="admin.profiles.manage.copy" title="WF_PROFILES_HELP_MANAGE_COPY" />
|
||||
<subtopic key="admin.profiles.manage.delete" title="WF_PROFILES_HELP_MANAGE_DELETE" />
|
||||
<subtopic key="admin.profiles.manage.export" title="WF_PROFILES_HELP_MANAGE_EXPORT" />
|
||||
<subtopic key="admin.profiles.manage.import" title="WF_PROFILES_HELP_MANAGE_IMPORT" />
|
||||
<subtopic key="admin.profiles.manage.ordering" title="WF_PROFILES_HELP_MANAGE_ORDERING" />
|
||||
<subtopic key="admin.profiles.manage.enable" title="WF_PROFILES_HELP_MANAGE_ENABLE" />
|
||||
</topic>
|
||||
<topic key="admin.profiles.edit" title="WF_PROFILES_HELP_EDIT">
|
||||
<subtopic key="admin.profiles.edit.setup" title="WF_PROFILES_HELP_EDIT_SETUP" />
|
||||
<subtopic key="admin.profiles.edit.features" title="WF_PROFILES_HELP_EDIT_FEATURES" />
|
||||
<subtopic key="admin.profiles.edit.editor" title="WF_PROFILES_HELP_EDIT_EDITOR" />
|
||||
<subtopic key="admin.profiles.edit.plugins" title="WF_PROFILES_HELP_EDIT_PLUGINS" />
|
||||
<subtopic key="admin.profiles.edit.widgets" title="WF_PROFILES_HELP_EDIT_WIDGETS" />
|
||||
</topic>
|
||||
</help>
|
||||
<profiles>
|
||||
<profile name="Default" default="default">
|
||||
<name>Default</name>
|
||||
<description>WF_PROFILES_DEFAULT_DESC</description>
|
||||
<users></users>
|
||||
<types></types>
|
||||
<components></components>
|
||||
<area>0</area>
|
||||
<device>desktop,tablet,phone</device>
|
||||
<rows>help,newdocument,undo,redo,spacer,bold,italic,underline,strikethrough,justifyfull,justifycenter,justifyleft,justifyright,spacer,blockquote,formatselect,styleselect,removeformat,cleanup;fontselect,fontsizeselect,fontcolor,spacer,clipboard,indent,outdent,lists,sub,sup,textcase,charmap,hr;directionality,fullscreen,print,searchreplace,spacer,table,style,attributes;visualaid,visualchars,visualblocks,nonbreaking,anchor,unlink,link,imgmanager,spellchecker,article</rows>
|
||||
<plugins>formatselect,styleselect,cleanup,fontselect,fontsizeselect,fontcolor,clipboard,lists,textcase,charmap,hr,directionality,fullscreen,print,searchreplace,table,style,attributes,visualchars,visualblocks,nonbreaking,anchor,link,imgmanager,spellchecker,article,spellchecker,article,browser,contextmenu,media,preview,source</plugins>
|
||||
<published>1</published>
|
||||
<ordering>1</ordering>
|
||||
<params>{"editor":{"toolbar_theme":"modern"}}</params>
|
||||
</profile>
|
||||
<profile name="Front End">
|
||||
<name>Front End</name>
|
||||
<description>WF_PROFILES_FRONTEND_DESC</description>
|
||||
<users></users>
|
||||
<types></types>
|
||||
<components></components>
|
||||
<area>1</area>
|
||||
<device>desktop,tablet,phone</device>
|
||||
<rows>help,newdocument,undo,redo,spacer,bold,italic,underline,strikethrough,justifyfull,justifycenter,justifyleft,justifyright,spacer,formatselect,styleselect;clipboard,searchreplace,indent,outdent,lists,cleanup,charmap,removeformat,hr,sub,sup,textcase,nonbreaking,visualchars,visualblocks;fullscreen,print,visualaid,style,attributes,anchor,unlink,link,imgmanager,spellchecker,article</rows>
|
||||
<plugins>charmap,contextmenu,help,clipboard,searchreplace,fullscreen,preview,print,style,textcase,nonbreaking,visualchars,visualblocks,attributes,imgmanager,anchor,link,spellchecker,article,lists,formatselect,styleselect,hr</plugins>
|
||||
<published>0</published>
|
||||
<ordering>2</ordering>
|
||||
<params>{"editor":{"toolbar_theme":"modern"}}</params>
|
||||
</profile>
|
||||
<profile name="Blogger">
|
||||
<name>Blogger</name>
|
||||
<description>Simple Blogging Profile</description>
|
||||
<users></users>
|
||||
<types></types>
|
||||
<components></components>
|
||||
<area>0</area>
|
||||
<device>desktop,tablet,phone</device>
|
||||
<rows>bold,italic,strikethrough,lists,blockquote,spacer,justifyleft,justifycenter,justifyright,spacer,link,unlink,imgmanager,article,spellchecker,fullscreen,kitchensink;formatselect,styleselect,underline,justifyfull,clipboard,removeformat,charmap,indent,outdent,undo,redo,help</rows>
|
||||
<plugins>link,imgmanager,article,spellchecker,fullscreen,kitchensink,clipboard,contextmenu,lists,formatselect,styleselect,textpattern</plugins>
|
||||
<published>0</published>
|
||||
<ordering>3</ordering>
|
||||
<params>{"editor":{"toolbar_theme":"modern"}}</params>
|
||||
</profile>
|
||||
<profile name="Mobile">
|
||||
<name>Mobile</name>
|
||||
<description>Sample Mobile Profile</description>
|
||||
<users></users>
|
||||
<types></types>
|
||||
<components></components>
|
||||
<area>0</area>
|
||||
<device>tablet,phone</device>
|
||||
<rows>undo,redo,spacer,bold,italic,underline,formatselect,spacer,justifyleft,justifycenter,justifyfull,justifyright,spacer,fullscreen,kitchensink;styleselect,lists,spellchecker,article,link,unlink</rows>
|
||||
<plugins>fullscreen,kitchensink,spellchecker,article,link,lists,formatselect,styleselect,textpattern</plugins>
|
||||
<published>0</published>
|
||||
<ordering>4</ordering>
|
||||
<params>{"editor":{"toolbar_theme":"modern.touch","resizing":"0","resize_horizontal":"0","resizing_use_cookie":"0","links":{"popups":{"default":"","jcemediabox":{"enable":"0"},"window":{"enable":"0"}}}}}</params>
|
||||
</profile>
|
||||
<profile>
|
||||
<name>Markdown</name>
|
||||
<description>Sample Markdown Profile</description>
|
||||
<users></users>
|
||||
<types>6,7,3,4,5,8</types>
|
||||
<components></components>
|
||||
<area>0</area>
|
||||
<device>desktop,tablet,phone</device>
|
||||
<rows>fullscreen,justifyleft,justifycenter,justifyfull,justifyright,link,unlink,imgmanager,styleselect</rows>
|
||||
<plugins>fullscreen,link,imgmanager,styleselect,media,textpattern</plugins>
|
||||
<published>0</published>
|
||||
<ordering>5</ordering>
|
||||
<params>{"editor":{"toolbar_theme":"modern"}}</params>
|
||||
</profile>
|
||||
</profiles>
|
||||
</profiles>
|
||||
18
administrator/components/com_jce/sql/mysql.sql
Normal file
18
administrator/components/com_jce/sql/mysql.sql
Normal file
@@ -0,0 +1,18 @@
|
||||
CREATE TABLE IF NOT EXISTS `#__wf_profiles` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`description` text NOT NULL,
|
||||
`users` text NOT NULL,
|
||||
`types` text NOT NULL,
|
||||
`components` text NOT NULL,
|
||||
`area` tinyint(3) NOT NULL,
|
||||
`device` varchar(255) NOT NULL,
|
||||
`rows` text NOT NULL,
|
||||
`plugins` text NOT NULL,
|
||||
`published` tinyint(3) NOT NULL,
|
||||
`ordering` int(11) NOT NULL,
|
||||
`checked_out` int unsigned,
|
||||
`checked_out_time` datetime NULL DEFAULT NULL,
|
||||
`params` text NOT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) DEFAULT CHARSET=utf8;
|
||||
18
administrator/components/com_jce/sql/postgresql.sql
Normal file
18
administrator/components/com_jce/sql/postgresql.sql
Normal file
@@ -0,0 +1,18 @@
|
||||
CREATE TABLE IF NOT EXISTS "#__wf_profiles" (
|
||||
"id" serial NOT NULL,
|
||||
"name" character varying(255) NOT NULL,
|
||||
"description" text NOT NULL,
|
||||
"users" text NOT NULL,
|
||||
"types" text NOT NULL,
|
||||
"components" text NOT NULL,
|
||||
"area" smallint NOT NULL,
|
||||
"device" character varying(255) NOT NULL,
|
||||
"rows" text NOT NULL,
|
||||
"plugins" text NOT NULL,
|
||||
"published" smallint NOT NULL,
|
||||
"ordering" integer NOT NULL,
|
||||
"checked_out" integer NOT NULL,
|
||||
"checked_out_time" timestamp without time zone NOT NULL,
|
||||
"params" text NOT NULL,
|
||||
PRIMARY KEY ("id")
|
||||
);
|
||||
24
administrator/components/com_jce/sql/sqlsrv.sql
Normal file
24
administrator/components/com_jce/sql/sqlsrv.sql
Normal file
@@ -0,0 +1,24 @@
|
||||
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[#__wf_profiles]') AND type in (N'U'))
|
||||
BEGIN
|
||||
CREATE TABLE [#__wf_profiles](
|
||||
[id] [bigint] IDENTITY(1,1) NOT NULL,
|
||||
[name] [nvarchar](250) NOT NULL,
|
||||
[description] [text] NOT NULL,
|
||||
[users] [text] NOT NULL,
|
||||
[types] [text] NOT NULL,
|
||||
[components] [nvarchar](max) NOT NULL,
|
||||
[area] [smallint] NOT NULL,
|
||||
[device] [nvarchar](250) NOT NULL,
|
||||
[rows] [nvarchar](max) NOT NULL,
|
||||
[plugins] [nvarchar](max) NOT NULL,
|
||||
[published] [smallint] NOT NULL,
|
||||
[ordering] [int] NOT NULL,
|
||||
[checked_out] [int] NOT NULL,
|
||||
[checked_out_time] [datetime] NOT NULL,
|
||||
[params] [nvarchar](max) NOT NULL,
|
||||
CONSTRAINT [PK_#__wf_profiles_id] PRIMARY KEY CLUSTERED
|
||||
(
|
||||
[id] ASC
|
||||
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF)
|
||||
)
|
||||
END;
|
||||
81
administrator/components/com_jce/tables/profiles.php
Normal file
81
administrator/components/com_jce/tables/profiles.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
|
||||
*/
|
||||
defined('JPATH_BASE') or die;
|
||||
|
||||
require_once(JPATH_ADMINISTRATOR . '/components/com_jce/helpers/encrypt.php');
|
||||
|
||||
class JceTableProfiles extends JTable
|
||||
{
|
||||
public function __construct(&$db)
|
||||
{
|
||||
parent::__construct('#__wf_profiles', 'id', $db);
|
||||
}
|
||||
|
||||
public function load($id = null, $reset = true)
|
||||
{
|
||||
$return = parent::load($id, $reset);
|
||||
|
||||
if ($return !== false) {
|
||||
// decrypt params
|
||||
if (!empty($this->params)) {
|
||||
$this->params = JceEncryptHelper::decrypt($this->params);
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloaded check function
|
||||
*
|
||||
* @return boolean True on success, false on failure
|
||||
*
|
||||
* @see Table::check()
|
||||
* @since 2.9.18
|
||||
*/
|
||||
public function check()
|
||||
{
|
||||
try
|
||||
{
|
||||
parent::check();
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
$this->setError($e->getMessage());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure any new items have compulsory fields set
|
||||
*/
|
||||
if (!$this->id)
|
||||
{
|
||||
if (!isset($this->device))
|
||||
{
|
||||
$this->device = 'desktop,tablet,phone';
|
||||
}
|
||||
|
||||
if (!isset($this->area))
|
||||
{
|
||||
$this->area = '0';
|
||||
}
|
||||
|
||||
// Params can be an empty json string for new tables
|
||||
if (empty($this->params))
|
||||
{
|
||||
$this->params = '{}';
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
446
administrator/components/com_jce/vendor/Defuse/Crypto/Core.php
vendored
Normal file
446
administrator/components/com_jce/vendor/Defuse/Crypto/Core.php
vendored
Normal file
@@ -0,0 +1,446 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto;
|
||||
|
||||
use Defuse\Crypto\Exception as Ex;
|
||||
|
||||
final class Core
|
||||
{
|
||||
const HEADER_VERSION_SIZE = 4;
|
||||
const MINIMUM_CIPHERTEXT_SIZE = 84;
|
||||
|
||||
const CURRENT_VERSION = "\xDE\xF5\x02\x00";
|
||||
|
||||
const CIPHER_METHOD = 'aes-256-ctr';
|
||||
const BLOCK_BYTE_SIZE = 16;
|
||||
const KEY_BYTE_SIZE = 32;
|
||||
const SALT_BYTE_SIZE = 32;
|
||||
const MAC_BYTE_SIZE = 32;
|
||||
const HASH_FUNCTION_NAME = 'sha256';
|
||||
const ENCRYPTION_INFO_STRING = 'DefusePHP|V2|KeyForEncryption';
|
||||
const AUTHENTICATION_INFO_STRING = 'DefusePHP|V2|KeyForAuthentication';
|
||||
const BUFFER_BYTE_SIZE = 1048576;
|
||||
|
||||
const LEGACY_CIPHER_METHOD = 'aes-128-cbc';
|
||||
const LEGACY_BLOCK_BYTE_SIZE = 16;
|
||||
const LEGACY_KEY_BYTE_SIZE = 16;
|
||||
const LEGACY_HASH_FUNCTION_NAME = 'sha256';
|
||||
const LEGACY_MAC_BYTE_SIZE = 32;
|
||||
const LEGACY_ENCRYPTION_INFO_STRING = 'DefusePHP|KeyForEncryption';
|
||||
const LEGACY_AUTHENTICATION_INFO_STRING = 'DefusePHP|KeyForAuthentication';
|
||||
|
||||
/*
|
||||
* V2.0 Format: VERSION (4 bytes) || SALT (32 bytes) || IV (16 bytes) ||
|
||||
* CIPHERTEXT (varies) || HMAC (32 bytes)
|
||||
*
|
||||
* V1.0 Format: HMAC (32 bytes) || IV (16 bytes) || CIPHERTEXT (varies).
|
||||
*/
|
||||
|
||||
/**
|
||||
* Adds an integer to a block-sized counter.
|
||||
*
|
||||
* @param string $ctr
|
||||
* @param int $inc
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function incrementCounter($ctr, $inc)
|
||||
{
|
||||
if (Core::ourStrlen($ctr) !== Core::BLOCK_BYTE_SIZE) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Trying to increment a nonce of the wrong size.'
|
||||
);
|
||||
}
|
||||
|
||||
if (! \is_int($inc)) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Trying to increment nonce by a non-integer.'
|
||||
);
|
||||
}
|
||||
|
||||
if ($inc < 0) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Trying to increment nonce by a negative amount.'
|
||||
);
|
||||
}
|
||||
|
||||
if ($inc > PHP_INT_MAX - 255) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Integer overflow may occur.'
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* We start at the rightmost byte (big-endian)
|
||||
* So, too, does OpenSSL: http://stackoverflow.com/a/3146214/2224584
|
||||
*/
|
||||
for ($i = Core::BLOCK_BYTE_SIZE - 1; $i >= 0; --$i) {
|
||||
$sum = \ord($ctr[$i]) + $inc;
|
||||
|
||||
/* Detect integer overflow and fail. */
|
||||
if (! \is_int($sum)) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Integer overflow in CTR mode nonce increment.'
|
||||
);
|
||||
}
|
||||
|
||||
$ctr[$i] = \pack('C', $sum & 0xFF);
|
||||
$inc = $sum >> 8;
|
||||
}
|
||||
return $ctr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random byte string of the specified length.
|
||||
*
|
||||
* @param int $octets
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function secureRandom($octets)
|
||||
{
|
||||
self::ensureFunctionExists('random_bytes');
|
||||
try {
|
||||
return \random_bytes($octets);
|
||||
} catch (\Exception $ex) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Your system does not have a secure random number generator.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the HKDF key derivation function specified in
|
||||
* http://tools.ietf.org/html/rfc5869.
|
||||
*
|
||||
* @param string $hash Hash Function
|
||||
* @param string $ikm Initial Keying Material
|
||||
* @param int $length How many bytes?
|
||||
* @param string $info What sort of key are we deriving?
|
||||
* @param string $salt
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @psalm-suppress UndefinedFunction - We're checking if the function exists first.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function HKDF($hash, $ikm, $length, $info = '', $salt = null)
|
||||
{
|
||||
static $nativeHKDF = null;
|
||||
if ($nativeHKDF === null) {
|
||||
$nativeHKDF = \is_callable('\\hash_hkdf');
|
||||
}
|
||||
if ($nativeHKDF) {
|
||||
return \hash_hkdf($hash, $ikm, $length, $info, $salt);
|
||||
}
|
||||
|
||||
$digest_length = Core::ourStrlen(\hash_hmac($hash, '', '', true));
|
||||
|
||||
// Sanity-check the desired output length.
|
||||
if (empty($length) || ! \is_int($length) ||
|
||||
$length < 0 || $length > 255 * $digest_length) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Bad output length requested of HKDF.'
|
||||
);
|
||||
}
|
||||
|
||||
// "if [salt] not provided, is set to a string of HashLen zeroes."
|
||||
if (\is_null($salt)) {
|
||||
$salt = \str_repeat("\x00", $digest_length);
|
||||
}
|
||||
|
||||
// HKDF-Extract:
|
||||
// PRK = HMAC-Hash(salt, IKM)
|
||||
// The salt is the HMAC key.
|
||||
$prk = \hash_hmac($hash, $ikm, $salt, true);
|
||||
|
||||
// HKDF-Expand:
|
||||
|
||||
// This check is useless, but it serves as a reminder to the spec.
|
||||
if (Core::ourStrlen($prk) < $digest_length) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
|
||||
// T(0) = ''
|
||||
$t = '';
|
||||
$last_block = '';
|
||||
for ($block_index = 1; Core::ourStrlen($t) < $length; ++$block_index) {
|
||||
// T(i) = HMAC-Hash(PRK, T(i-1) | info | 0x??)
|
||||
$last_block = \hash_hmac(
|
||||
$hash,
|
||||
$last_block . $info . \chr($block_index),
|
||||
$prk,
|
||||
true
|
||||
);
|
||||
// T = T(1) | T(2) | T(3) | ... | T(N)
|
||||
$t .= $last_block;
|
||||
}
|
||||
|
||||
// ORM = first L octets of T
|
||||
/** @var string $orm */
|
||||
$orm = Core::ourSubstr($t, 0, $length);
|
||||
if (!\is_string($orm)) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
return $orm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if two equal-length strings are the same without leaking
|
||||
* information through side channels.
|
||||
*
|
||||
* @param string $expected
|
||||
* @param string $given
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function hashEquals($expected, $given)
|
||||
{
|
||||
static $native = null;
|
||||
if ($native === null) {
|
||||
$native = \function_exists('hash_equals');
|
||||
}
|
||||
if ($native) {
|
||||
return \hash_equals($expected, $given);
|
||||
}
|
||||
|
||||
// We can't just compare the strings with '==', since it would make
|
||||
// timing attacks possible. We could use the XOR-OR constant-time
|
||||
// comparison algorithm, but that may not be a reliable defense in an
|
||||
// interpreted language. So we use the approach of HMACing both strings
|
||||
// with a random key and comparing the HMACs.
|
||||
|
||||
// We're not attempting to make variable-length string comparison
|
||||
// secure, as that's very difficult. Make sure the strings are the same
|
||||
// length.
|
||||
if (Core::ourStrlen($expected) !== Core::ourStrlen($given)) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
|
||||
$blind = Core::secureRandom(32);
|
||||
$message_compare = \hash_hmac(Core::HASH_FUNCTION_NAME, $given, $blind);
|
||||
$correct_compare = \hash_hmac(Core::HASH_FUNCTION_NAME, $expected, $blind);
|
||||
return $correct_compare === $message_compare;
|
||||
}
|
||||
/**
|
||||
* Throws an exception if the constant doesn't exist.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*/
|
||||
public static function ensureConstantExists($name)
|
||||
{
|
||||
if (! \defined($name)) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception if the function doesn't exist.
|
||||
*
|
||||
* @param string $name
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*/
|
||||
public static function ensureFunctionExists($name)
|
||||
{
|
||||
if (! \function_exists($name)) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We need these strlen() and substr() functions because when
|
||||
* 'mbstring.func_overload' is set in php.ini, the standard strlen() and
|
||||
* substr() are replaced by mb_strlen() and mb_substr().
|
||||
*/
|
||||
|
||||
/**
|
||||
* Computes the length of a string in bytes.
|
||||
*
|
||||
* @param string $str
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function ourStrlen($str)
|
||||
{
|
||||
static $exists = null;
|
||||
if ($exists === null) {
|
||||
$exists = \function_exists('mb_strlen');
|
||||
}
|
||||
if ($exists) {
|
||||
$length = \mb_strlen($str, '8bit');
|
||||
if ($length === false) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
return $length;
|
||||
} else {
|
||||
return \strlen($str);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Behaves roughly like the function substr() in PHP 7 does.
|
||||
*
|
||||
* @param string $str
|
||||
* @param int $start
|
||||
* @param int $length
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string|bool
|
||||
*/
|
||||
public static function ourSubstr($str, $start, $length = null)
|
||||
{
|
||||
static $exists = null;
|
||||
if ($exists === null) {
|
||||
$exists = \function_exists('mb_substr');
|
||||
}
|
||||
|
||||
if ($exists) {
|
||||
// mb_substr($str, 0, NULL, '8bit') returns an empty string on PHP
|
||||
// 5.3, so we have to find the length ourselves.
|
||||
if (! isset($length)) {
|
||||
if ($start >= 0) {
|
||||
$length = Core::ourStrlen($str) - $start;
|
||||
} else {
|
||||
$length = -$start;
|
||||
}
|
||||
}
|
||||
|
||||
// This is required to make mb_substr behavior identical to substr.
|
||||
// Without this, mb_substr() would return false, contra to what the
|
||||
// PHP documentation says (it doesn't say it can return false.)
|
||||
if ($start === Core::ourStrlen($str) && $length === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ($start > Core::ourStrlen($str)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$substr = \mb_substr($str, $start, $length, '8bit');
|
||||
if (Core::ourStrlen($substr) !== $length) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Your version of PHP has bug #66797. Its implementation of
|
||||
mb_substr() is incorrect. See the details here:
|
||||
https://bugs.php.net/bug.php?id=66797'
|
||||
);
|
||||
}
|
||||
return $substr;
|
||||
}
|
||||
|
||||
// Unlike mb_substr(), substr() doesn't accept NULL for length
|
||||
if (isset($length)) {
|
||||
return \substr($str, $start, $length);
|
||||
} else {
|
||||
return \substr($str, $start);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the PBKDF2 password-based key derivation function.
|
||||
*
|
||||
* The PBKDF2 function is defined in RFC 2898. Test vectors can be found in
|
||||
* RFC 6070. This implementation of PBKDF2 was originally created by Taylor
|
||||
* Hornby, with improvements from http://www.variations-of-shadow.com/.
|
||||
*
|
||||
* @param string $algorithm The hash algorithm to use. Recommended: SHA256
|
||||
* @param string $password The password.
|
||||
* @param string $salt A salt that is unique to the password.
|
||||
* @param int $count Iteration count. Higher is better, but slower. Recommended: At least 1000.
|
||||
* @param int $key_length The length of the derived key in bytes.
|
||||
* @param bool $raw_output If true, the key is returned in raw binary format. Hex encoded otherwise.
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string A $key_length-byte key derived from the password and salt.
|
||||
*/
|
||||
public static function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
|
||||
{
|
||||
// Type checks:
|
||||
if (! \is_string($algorithm)) {
|
||||
throw new \InvalidArgumentException(
|
||||
'pbkdf2(): algorithm must be a string'
|
||||
);
|
||||
}
|
||||
if (! \is_string($password)) {
|
||||
throw new \InvalidArgumentException(
|
||||
'pbkdf2(): password must be a string'
|
||||
);
|
||||
}
|
||||
if (! \is_string($salt)) {
|
||||
throw new \InvalidArgumentException(
|
||||
'pbkdf2(): salt must be a string'
|
||||
);
|
||||
}
|
||||
// Coerce strings to integers with no information loss or overflow
|
||||
$count += 0;
|
||||
$key_length += 0;
|
||||
|
||||
$algorithm = \strtolower($algorithm);
|
||||
if (! \in_array($algorithm, \hash_algos(), true)) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Invalid or unsupported hash algorithm.'
|
||||
);
|
||||
}
|
||||
|
||||
// Whitelist, or we could end up with people using CRC32.
|
||||
$ok_algorithms = [
|
||||
'sha1', 'sha224', 'sha256', 'sha384', 'sha512',
|
||||
'ripemd160', 'ripemd256', 'ripemd320', 'whirlpool',
|
||||
];
|
||||
if (! \in_array($algorithm, $ok_algorithms, true)) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Algorithm is not a secure cryptographic hash function.'
|
||||
);
|
||||
}
|
||||
|
||||
if ($count <= 0 || $key_length <= 0) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Invalid PBKDF2 parameters.'
|
||||
);
|
||||
}
|
||||
|
||||
if (\function_exists('hash_pbkdf2')) {
|
||||
// The output length is in NIBBLES (4-bits) if $raw_output is false!
|
||||
if (! $raw_output) {
|
||||
$key_length = $key_length * 2;
|
||||
}
|
||||
return \hash_pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output);
|
||||
}
|
||||
|
||||
$hash_length = Core::ourStrlen(\hash($algorithm, '', true));
|
||||
$block_count = \ceil($key_length / $hash_length);
|
||||
|
||||
$output = '';
|
||||
for ($i = 1; $i <= $block_count; $i++) {
|
||||
// $i encoded as 4 bytes, big endian.
|
||||
$last = $salt . \pack('N', $i);
|
||||
// first iteration
|
||||
$last = $xorsum = \hash_hmac($algorithm, $last, $password, true);
|
||||
// perform the other $count - 1 iterations
|
||||
for ($j = 1; $j < $count; $j++) {
|
||||
$xorsum ^= ($last = \hash_hmac($algorithm, $last, $password, true));
|
||||
}
|
||||
$output .= $xorsum;
|
||||
}
|
||||
|
||||
if ($raw_output) {
|
||||
return (string) Core::ourSubstr($output, 0, $key_length);
|
||||
} else {
|
||||
return Encoding::binToHex((string) Core::ourSubstr($output, 0, $key_length));
|
||||
}
|
||||
}
|
||||
}
|
||||
455
administrator/components/com_jce/vendor/Defuse/Crypto/Crypto.php
vendored
Normal file
455
administrator/components/com_jce/vendor/Defuse/Crypto/Crypto.php
vendored
Normal file
@@ -0,0 +1,455 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto;
|
||||
|
||||
use Defuse\Crypto\Exception as Ex;
|
||||
|
||||
class Crypto
|
||||
{
|
||||
/**
|
||||
* Encrypts a string with a Key.
|
||||
*
|
||||
* @param string $plaintext
|
||||
* @param Key $key
|
||||
* @param bool $raw_binary
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function encrypt($plaintext, Key $key, $raw_binary = false)
|
||||
{
|
||||
if (!\is_string($plaintext)) {
|
||||
throw new \TypeError(
|
||||
'String expected for argument 1. ' . \ucfirst(\gettype($plaintext)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
if (!\is_bool($raw_binary)) {
|
||||
throw new \TypeError(
|
||||
'Boolean expected for argument 3. ' . \ucfirst(\gettype($raw_binary)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
return self::encryptInternal(
|
||||
$plaintext,
|
||||
KeyOrPassword::createFromKey($key),
|
||||
$raw_binary
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a string with a password, using a slow key derivation function
|
||||
* to make password cracking more expensive.
|
||||
*
|
||||
* @param string $plaintext
|
||||
* @param string $password
|
||||
* @param bool $raw_binary
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function encryptWithPassword($plaintext, $password, $raw_binary = false)
|
||||
{
|
||||
if (!\is_string($plaintext)) {
|
||||
throw new \TypeError(
|
||||
'String expected for argument 1. ' . \ucfirst(\gettype($plaintext)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
if (!\is_string($password)) {
|
||||
throw new \TypeError(
|
||||
'String expected for argument 2. ' . \ucfirst(\gettype($password)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
if (!\is_bool($raw_binary)) {
|
||||
throw new \TypeError(
|
||||
'Boolean expected for argument 3. ' . \ucfirst(\gettype($raw_binary)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
return self::encryptInternal(
|
||||
$plaintext,
|
||||
KeyOrPassword::createFromPassword($password),
|
||||
$raw_binary
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a ciphertext to a string with a Key.
|
||||
*
|
||||
* @param string $ciphertext
|
||||
* @param Key $key
|
||||
* @param bool $raw_binary
|
||||
*
|
||||
* @throws \TypeError
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function decrypt($ciphertext, Key $key, $raw_binary = false)
|
||||
{
|
||||
if (!\is_string($ciphertext)) {
|
||||
throw new \TypeError(
|
||||
'String expected for argument 1. ' . \ucfirst(\gettype($ciphertext)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
if (!\is_bool($raw_binary)) {
|
||||
throw new \TypeError(
|
||||
'Boolean expected for argument 3. ' . \ucfirst(\gettype($raw_binary)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
return self::decryptInternal(
|
||||
$ciphertext,
|
||||
KeyOrPassword::createFromKey($key),
|
||||
$raw_binary
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a ciphertext to a string with a password, using a slow key
|
||||
* derivation function to make password cracking more expensive.
|
||||
*
|
||||
* @param string $ciphertext
|
||||
* @param string $password
|
||||
* @param bool $raw_binary
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function decryptWithPassword($ciphertext, $password, $raw_binary = false)
|
||||
{
|
||||
if (!\is_string($ciphertext)) {
|
||||
throw new \TypeError(
|
||||
'String expected for argument 1. ' . \ucfirst(\gettype($ciphertext)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
if (!\is_string($password)) {
|
||||
throw new \TypeError(
|
||||
'String expected for argument 2. ' . \ucfirst(\gettype($password)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
if (!\is_bool($raw_binary)) {
|
||||
throw new \TypeError(
|
||||
'Boolean expected for argument 3. ' . \ucfirst(\gettype($raw_binary)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
return self::decryptInternal(
|
||||
$ciphertext,
|
||||
KeyOrPassword::createFromPassword($password),
|
||||
$raw_binary
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a legacy ciphertext produced by version 1 of this library.
|
||||
*
|
||||
* @param string $ciphertext
|
||||
* @param string $key
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function legacyDecrypt($ciphertext, $key)
|
||||
{
|
||||
if (!\is_string($ciphertext)) {
|
||||
throw new \TypeError(
|
||||
'String expected for argument 1. ' . \ucfirst(\gettype($ciphertext)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
if (!\is_string($key)) {
|
||||
throw new \TypeError(
|
||||
'String expected for argument 2. ' . \ucfirst(\gettype($key)) . ' given instead.'
|
||||
);
|
||||
}
|
||||
|
||||
RuntimeTests::runtimeTest();
|
||||
|
||||
// Extract the HMAC from the front of the ciphertext.
|
||||
if (Core::ourStrlen($ciphertext) <= Core::LEGACY_MAC_BYTE_SIZE) {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'Ciphertext is too short.'
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
$hmac = Core::ourSubstr($ciphertext, 0, Core::LEGACY_MAC_BYTE_SIZE);
|
||||
if (!\is_string($hmac)) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
$messageCiphertext = Core::ourSubstr($ciphertext, Core::LEGACY_MAC_BYTE_SIZE);
|
||||
if (!\is_string($messageCiphertext)) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
|
||||
// Regenerate the same authentication sub-key.
|
||||
$akey = Core::HKDF(
|
||||
Core::LEGACY_HASH_FUNCTION_NAME,
|
||||
$key,
|
||||
Core::LEGACY_KEY_BYTE_SIZE,
|
||||
Core::LEGACY_AUTHENTICATION_INFO_STRING,
|
||||
null
|
||||
);
|
||||
|
||||
if (self::verifyHMAC($hmac, $messageCiphertext, $akey)) {
|
||||
// Regenerate the same encryption sub-key.
|
||||
$ekey = Core::HKDF(
|
||||
Core::LEGACY_HASH_FUNCTION_NAME,
|
||||
$key,
|
||||
Core::LEGACY_KEY_BYTE_SIZE,
|
||||
Core::LEGACY_ENCRYPTION_INFO_STRING,
|
||||
null
|
||||
);
|
||||
|
||||
// Extract the IV from the ciphertext.
|
||||
if (Core::ourStrlen($messageCiphertext) <= Core::LEGACY_BLOCK_BYTE_SIZE) {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'Ciphertext is too short.'
|
||||
);
|
||||
}
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
$iv = Core::ourSubstr($messageCiphertext, 0, Core::LEGACY_BLOCK_BYTE_SIZE);
|
||||
if (!\is_string($iv)) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
$actualCiphertext = Core::ourSubstr($messageCiphertext, Core::LEGACY_BLOCK_BYTE_SIZE);
|
||||
if (!\is_string($actualCiphertext)) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
|
||||
// Do the decryption.
|
||||
$plaintext = self::plainDecrypt($actualCiphertext, $ekey, $iv, Core::LEGACY_CIPHER_METHOD);
|
||||
return $plaintext;
|
||||
} else {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'Integrity check failed.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a string with either a key or a password.
|
||||
*
|
||||
* @param string $plaintext
|
||||
* @param KeyOrPassword $secret
|
||||
* @param bool $raw_binary
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function encryptInternal($plaintext, KeyOrPassword $secret, $raw_binary)
|
||||
{
|
||||
RuntimeTests::runtimeTest();
|
||||
|
||||
$salt = Core::secureRandom(Core::SALT_BYTE_SIZE);
|
||||
$keys = $secret->deriveKeys($salt);
|
||||
$ekey = $keys->getEncryptionKey();
|
||||
$akey = $keys->getAuthenticationKey();
|
||||
$iv = Core::secureRandom(Core::BLOCK_BYTE_SIZE);
|
||||
|
||||
$ciphertext = Core::CURRENT_VERSION . $salt . $iv . self::plainEncrypt($plaintext, $ekey, $iv);
|
||||
$auth = \hash_hmac(Core::HASH_FUNCTION_NAME, $ciphertext, $akey, true);
|
||||
$ciphertext = $ciphertext . $auth;
|
||||
|
||||
if ($raw_binary) {
|
||||
return $ciphertext;
|
||||
}
|
||||
return Encoding::binToHex($ciphertext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a ciphertext to a string with either a key or a password.
|
||||
*
|
||||
* @param string $ciphertext
|
||||
* @param KeyOrPassword $secret
|
||||
* @param bool $raw_binary
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function decryptInternal($ciphertext, KeyOrPassword $secret, $raw_binary)
|
||||
{
|
||||
RuntimeTests::runtimeTest();
|
||||
|
||||
if (! $raw_binary) {
|
||||
try {
|
||||
$ciphertext = Encoding::hexToBin($ciphertext);
|
||||
} catch (Ex\BadFormatException $ex) {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'Ciphertext has invalid hex encoding.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (Core::ourStrlen($ciphertext) < Core::MINIMUM_CIPHERTEXT_SIZE) {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'Ciphertext is too short.'
|
||||
);
|
||||
}
|
||||
|
||||
// Get and check the version header.
|
||||
/** @var string $header */
|
||||
$header = Core::ourSubstr($ciphertext, 0, Core::HEADER_VERSION_SIZE);
|
||||
if ($header !== Core::CURRENT_VERSION) {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'Bad version header.'
|
||||
);
|
||||
}
|
||||
|
||||
// Get the salt.
|
||||
/** @var string $salt */
|
||||
$salt = Core::ourSubstr(
|
||||
$ciphertext,
|
||||
Core::HEADER_VERSION_SIZE,
|
||||
Core::SALT_BYTE_SIZE
|
||||
);
|
||||
if (!\is_string($salt)) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
|
||||
// Get the IV.
|
||||
/** @var string $iv */
|
||||
$iv = Core::ourSubstr(
|
||||
$ciphertext,
|
||||
Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE,
|
||||
Core::BLOCK_BYTE_SIZE
|
||||
);
|
||||
if (!\is_string($iv)) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
|
||||
// Get the HMAC.
|
||||
/** @var string $hmac */
|
||||
$hmac = Core::ourSubstr(
|
||||
$ciphertext,
|
||||
Core::ourStrlen($ciphertext) - Core::MAC_BYTE_SIZE,
|
||||
Core::MAC_BYTE_SIZE
|
||||
);
|
||||
if (!\is_string($hmac)) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
|
||||
// Get the actual encrypted ciphertext.
|
||||
/** @var string $encrypted */
|
||||
$encrypted = Core::ourSubstr(
|
||||
$ciphertext,
|
||||
Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE +
|
||||
Core::BLOCK_BYTE_SIZE,
|
||||
Core::ourStrlen($ciphertext) - Core::MAC_BYTE_SIZE - Core::SALT_BYTE_SIZE -
|
||||
Core::BLOCK_BYTE_SIZE - Core::HEADER_VERSION_SIZE
|
||||
);
|
||||
if (!\is_string($encrypted)) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
|
||||
// Derive the separate encryption and authentication keys from the key
|
||||
// or password, whichever it is.
|
||||
$keys = $secret->deriveKeys($salt);
|
||||
|
||||
if (self::verifyHMAC($hmac, $header . $salt . $iv . $encrypted, $keys->getAuthenticationKey())) {
|
||||
$plaintext = self::plainDecrypt($encrypted, $keys->getEncryptionKey(), $iv, Core::CIPHER_METHOD);
|
||||
return $plaintext;
|
||||
} else {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'Integrity check failed.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw unauthenticated encryption (insecure on its own).
|
||||
*
|
||||
* @param string $plaintext
|
||||
* @param string $key
|
||||
* @param string $iv
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function plainEncrypt($plaintext, $key, $iv)
|
||||
{
|
||||
Core::ensureConstantExists('OPENSSL_RAW_DATA');
|
||||
Core::ensureFunctionExists('openssl_encrypt');
|
||||
/** @var string $ciphertext */
|
||||
$ciphertext = \openssl_encrypt(
|
||||
$plaintext,
|
||||
Core::CIPHER_METHOD,
|
||||
$key,
|
||||
OPENSSL_RAW_DATA,
|
||||
$iv
|
||||
);
|
||||
|
||||
if (!\is_string($ciphertext)) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'openssl_encrypt() failed.'
|
||||
);
|
||||
}
|
||||
|
||||
return $ciphertext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Raw unauthenticated decryption (insecure on its own).
|
||||
*
|
||||
* @param string $ciphertext
|
||||
* @param string $key
|
||||
* @param string $iv
|
||||
* @param string $cipherMethod
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function plainDecrypt($ciphertext, $key, $iv, $cipherMethod)
|
||||
{
|
||||
Core::ensureConstantExists('OPENSSL_RAW_DATA');
|
||||
Core::ensureFunctionExists('openssl_decrypt');
|
||||
|
||||
/** @var string $plaintext */
|
||||
$plaintext = \openssl_decrypt(
|
||||
$ciphertext,
|
||||
$cipherMethod,
|
||||
$key,
|
||||
OPENSSL_RAW_DATA,
|
||||
$iv
|
||||
);
|
||||
if (!\is_string($plaintext)) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'openssl_decrypt() failed.'
|
||||
);
|
||||
}
|
||||
|
||||
return $plaintext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies an HMAC without leaking information through side-channels.
|
||||
*
|
||||
* @param string $expected_hmac
|
||||
* @param string $message
|
||||
* @param string $key
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function verifyHMAC($expected_hmac, $message, $key)
|
||||
{
|
||||
$message_hmac = \hash_hmac(Core::HASH_FUNCTION_NAME, $message, $key, true);
|
||||
return Core::hashEquals($message_hmac, $expected_hmac);
|
||||
}
|
||||
}
|
||||
50
administrator/components/com_jce/vendor/Defuse/Crypto/DerivedKeys.php
vendored
Normal file
50
administrator/components/com_jce/vendor/Defuse/Crypto/DerivedKeys.php
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto;
|
||||
|
||||
/**
|
||||
* Class DerivedKeys
|
||||
* @package Defuse\Crypto
|
||||
*/
|
||||
final class DerivedKeys
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $akey = '';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $ekey = '';
|
||||
|
||||
/**
|
||||
* Returns the authentication key.
|
||||
* @return string
|
||||
*/
|
||||
public function getAuthenticationKey()
|
||||
{
|
||||
return $this->akey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the encryption key.
|
||||
* @return string
|
||||
*/
|
||||
public function getEncryptionKey()
|
||||
{
|
||||
return $this->ekey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for DerivedKeys.
|
||||
*
|
||||
* @param string $akey
|
||||
* @param string $ekey
|
||||
*/
|
||||
public function __construct($akey, $ekey)
|
||||
{
|
||||
$this->akey = $akey;
|
||||
$this->ekey = $ekey;
|
||||
}
|
||||
}
|
||||
270
administrator/components/com_jce/vendor/Defuse/Crypto/Encoding.php
vendored
Normal file
270
administrator/components/com_jce/vendor/Defuse/Crypto/Encoding.php
vendored
Normal file
@@ -0,0 +1,270 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto;
|
||||
|
||||
use Defuse\Crypto\Exception as Ex;
|
||||
|
||||
final class Encoding
|
||||
{
|
||||
const CHECKSUM_BYTE_SIZE = 32;
|
||||
const CHECKSUM_HASH_ALGO = 'sha256';
|
||||
const SERIALIZE_HEADER_BYTES = 4;
|
||||
|
||||
/**
|
||||
* Converts a byte string to a hexadecimal string without leaking
|
||||
* information through side channels.
|
||||
*
|
||||
* @param string $byte_string
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function binToHex($byte_string)
|
||||
{
|
||||
$hex = '';
|
||||
$len = Core::ourStrlen($byte_string);
|
||||
for ($i = 0; $i < $len; ++$i) {
|
||||
$c = \ord($byte_string[$i]) & 0xf;
|
||||
$b = \ord($byte_string[$i]) >> 4;
|
||||
$hex .= \pack(
|
||||
'CC',
|
||||
87 + $b + ((($b - 10) >> 8) & ~38),
|
||||
87 + $c + ((($c - 10) >> 8) & ~38)
|
||||
);
|
||||
}
|
||||
return $hex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a hexadecimal string into a byte string without leaking
|
||||
* information through side channels.
|
||||
*
|
||||
* @param string $hex_string
|
||||
*
|
||||
* @throws Ex\BadFormatException
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function hexToBin($hex_string)
|
||||
{
|
||||
$hex_pos = 0;
|
||||
$bin = '';
|
||||
$hex_len = Core::ourStrlen($hex_string);
|
||||
$state = 0;
|
||||
$c_acc = 0;
|
||||
|
||||
while ($hex_pos < $hex_len) {
|
||||
$c = \ord($hex_string[$hex_pos]);
|
||||
$c_num = $c ^ 48;
|
||||
$c_num0 = ($c_num - 10) >> 8;
|
||||
$c_alpha = ($c & ~32) - 55;
|
||||
$c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8;
|
||||
if (($c_num0 | $c_alpha0) === 0) {
|
||||
throw new Ex\BadFormatException(
|
||||
'Encoding::hexToBin() input is not a hex string.'
|
||||
);
|
||||
}
|
||||
$c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0);
|
||||
if ($state === 0) {
|
||||
$c_acc = $c_val * 16;
|
||||
} else {
|
||||
$bin .= \pack('C', $c_acc | $c_val);
|
||||
}
|
||||
$state ^= 1;
|
||||
++$hex_pos;
|
||||
}
|
||||
return $bin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove trialing whitespace without table look-ups or branches.
|
||||
*
|
||||
* Calling this function may leak the length of the string as well as the
|
||||
* number of trailing whitespace characters through side-channels.
|
||||
*
|
||||
* @param string $string
|
||||
* @return string
|
||||
*/
|
||||
public static function trimTrailingWhitespace($string = '')
|
||||
{
|
||||
$length = Core::ourStrlen($string);
|
||||
if ($length < 1) {
|
||||
return '';
|
||||
}
|
||||
do {
|
||||
$prevLength = $length;
|
||||
$last = $length - 1;
|
||||
$chr = \ord($string[$last]);
|
||||
|
||||
/* Null Byte (0x00), a.k.a. \0 */
|
||||
// if ($chr === 0x00) $length -= 1;
|
||||
$sub = (($chr - 1) >> 8 ) & 1;
|
||||
$length -= $sub;
|
||||
$last -= $sub;
|
||||
|
||||
/* Horizontal Tab (0x09) a.k.a. \t */
|
||||
$chr = \ord($string[$last]);
|
||||
// if ($chr === 0x09) $length -= 1;
|
||||
$sub = (((0x08 - $chr) & ($chr - 0x0a)) >> 8) & 1;
|
||||
$length -= $sub;
|
||||
$last -= $sub;
|
||||
|
||||
/* New Line (0x0a), a.k.a. \n */
|
||||
$chr = \ord($string[$last]);
|
||||
// if ($chr === 0x0a) $length -= 1;
|
||||
$sub = (((0x09 - $chr) & ($chr - 0x0b)) >> 8) & 1;
|
||||
$length -= $sub;
|
||||
$last -= $sub;
|
||||
|
||||
/* Carriage Return (0x0D), a.k.a. \r */
|
||||
$chr = \ord($string[$last]);
|
||||
// if ($chr === 0x0d) $length -= 1;
|
||||
$sub = (((0x0c - $chr) & ($chr - 0x0e)) >> 8) & 1;
|
||||
$length -= $sub;
|
||||
$last -= $sub;
|
||||
|
||||
/* Space */
|
||||
$chr = \ord($string[$last]);
|
||||
// if ($chr === 0x20) $length -= 1;
|
||||
$sub = (((0x1f - $chr) & ($chr - 0x21)) >> 8) & 1;
|
||||
$length -= $sub;
|
||||
} while ($prevLength !== $length && $length > 0);
|
||||
return (string) Core::ourSubstr($string, 0, $length);
|
||||
}
|
||||
|
||||
/*
|
||||
* SECURITY NOTE ON APPLYING CHECKSUMS TO SECRETS:
|
||||
*
|
||||
* The checksum introduces a potential security weakness. For example,
|
||||
* suppose we apply a checksum to a key, and that an adversary has an
|
||||
* exploit against the process containing the key, such that they can
|
||||
* overwrite an arbitrary byte of memory and then cause the checksum to
|
||||
* be verified and learn the result.
|
||||
*
|
||||
* In this scenario, the adversary can extract the key one byte at
|
||||
* a time by overwriting it with their guess of its value and then
|
||||
* asking if the checksum matches. If it does, their guess was right.
|
||||
* This kind of attack may be more easy to implement and more reliable
|
||||
* than a remote code execution attack.
|
||||
*
|
||||
* This attack also applies to authenticated encryption as a whole, in
|
||||
* the situation where the adversary can overwrite a byte of the key
|
||||
* and then cause a valid ciphertext to be decrypted, and then
|
||||
* determine whether the MAC check passed or failed.
|
||||
*
|
||||
* By using the full SHA256 hash instead of truncating it, I'm ensuring
|
||||
* that both ways of going about the attack are equivalently difficult.
|
||||
* A shorter checksum of say 32 bits might be more useful to the
|
||||
* adversary as an oracle in case their writes are coarser grained.
|
||||
*
|
||||
* Because the scenario assumes a serious vulnerability, we don't try
|
||||
* to prevent attacks of this style.
|
||||
*/
|
||||
|
||||
/**
|
||||
* INTERNAL USE ONLY: Applies a version header, applies a checksum, and
|
||||
* then encodes a byte string into a range of printable ASCII characters.
|
||||
*
|
||||
* @param string $header
|
||||
* @param string $bytes
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function saveBytesToChecksummedAsciiSafeString($header, $bytes)
|
||||
{
|
||||
// Headers must be a constant length to prevent one type's header from
|
||||
// being a prefix of another type's header, leading to ambiguity.
|
||||
if (Core::ourStrlen($header) !== self::SERIALIZE_HEADER_BYTES) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Header must be ' . self::SERIALIZE_HEADER_BYTES . ' bytes.'
|
||||
);
|
||||
}
|
||||
|
||||
return Encoding::binToHex(
|
||||
$header .
|
||||
$bytes .
|
||||
\hash(
|
||||
self::CHECKSUM_HASH_ALGO,
|
||||
$header . $bytes,
|
||||
true
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL USE ONLY: Decodes, verifies the header and checksum, and returns
|
||||
* the encoded byte string.
|
||||
*
|
||||
* @param string $expected_header
|
||||
* @param string $string
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\BadFormatException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function loadBytesFromChecksummedAsciiSafeString($expected_header, $string)
|
||||
{
|
||||
// Headers must be a constant length to prevent one type's header from
|
||||
// being a prefix of another type's header, leading to ambiguity.
|
||||
if (Core::ourStrlen($expected_header) !== self::SERIALIZE_HEADER_BYTES) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Header must be 4 bytes.'
|
||||
);
|
||||
}
|
||||
|
||||
/* If you get an exception here when attempting to load from a file, first pass your
|
||||
key to Encoding::trimTrailingWhitespace() to remove newline characters, etc. */
|
||||
$bytes = Encoding::hexToBin($string);
|
||||
|
||||
/* Make sure we have enough bytes to get the version header and checksum. */
|
||||
if (Core::ourStrlen($bytes) < self::SERIALIZE_HEADER_BYTES + self::CHECKSUM_BYTE_SIZE) {
|
||||
throw new Ex\BadFormatException(
|
||||
'Encoded data is shorter than expected.'
|
||||
);
|
||||
}
|
||||
|
||||
/* Grab the version header. */
|
||||
$actual_header = (string) Core::ourSubstr($bytes, 0, self::SERIALIZE_HEADER_BYTES);
|
||||
|
||||
if ($actual_header !== $expected_header) {
|
||||
throw new Ex\BadFormatException(
|
||||
'Invalid header.'
|
||||
);
|
||||
}
|
||||
|
||||
/* Grab the bytes that are part of the checksum. */
|
||||
$checked_bytes = (string) Core::ourSubstr(
|
||||
$bytes,
|
||||
0,
|
||||
Core::ourStrlen($bytes) - self::CHECKSUM_BYTE_SIZE
|
||||
);
|
||||
|
||||
/* Grab the included checksum. */
|
||||
$checksum_a = (string) Core::ourSubstr(
|
||||
$bytes,
|
||||
Core::ourStrlen($bytes) - self::CHECKSUM_BYTE_SIZE,
|
||||
self::CHECKSUM_BYTE_SIZE
|
||||
);
|
||||
|
||||
/* Re-compute the checksum. */
|
||||
$checksum_b = \hash(self::CHECKSUM_HASH_ALGO, $checked_bytes, true);
|
||||
|
||||
/* Check if the checksum matches. */
|
||||
if (! Core::hashEquals($checksum_a, $checksum_b)) {
|
||||
throw new Ex\BadFormatException(
|
||||
"Data is corrupted, the checksum doesn't match"
|
||||
);
|
||||
}
|
||||
|
||||
return (string) Core::ourSubstr(
|
||||
$bytes,
|
||||
self::SERIALIZE_HEADER_BYTES,
|
||||
Core::ourStrlen($bytes) - self::SERIALIZE_HEADER_BYTES - self::CHECKSUM_BYTE_SIZE
|
||||
);
|
||||
}
|
||||
}
|
||||
7
administrator/components/com_jce/vendor/Defuse/Crypto/Exception/BadFormatException.php
vendored
Normal file
7
administrator/components/com_jce/vendor/Defuse/Crypto/Exception/BadFormatException.php
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto\Exception;
|
||||
|
||||
class BadFormatException extends \Defuse\Crypto\Exception\CryptoException
|
||||
{
|
||||
}
|
||||
7
administrator/components/com_jce/vendor/Defuse/Crypto/Exception/CryptoException.php
vendored
Normal file
7
administrator/components/com_jce/vendor/Defuse/Crypto/Exception/CryptoException.php
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto\Exception;
|
||||
|
||||
class CryptoException extends \Exception
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto\Exception;
|
||||
|
||||
class EnvironmentIsBrokenException extends \Defuse\Crypto\Exception\CryptoException
|
||||
{
|
||||
}
|
||||
7
administrator/components/com_jce/vendor/Defuse/Crypto/Exception/IOException.php
vendored
Normal file
7
administrator/components/com_jce/vendor/Defuse/Crypto/Exception/IOException.php
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto\Exception;
|
||||
|
||||
class IOException extends \Defuse\Crypto\Exception\CryptoException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto\Exception;
|
||||
|
||||
class WrongKeyOrModifiedCiphertextException extends \Defuse\Crypto\Exception\CryptoException
|
||||
{
|
||||
}
|
||||
784
administrator/components/com_jce/vendor/Defuse/Crypto/File.php
vendored
Normal file
784
administrator/components/com_jce/vendor/Defuse/Crypto/File.php
vendored
Normal file
@@ -0,0 +1,784 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto;
|
||||
|
||||
use Defuse\Crypto\Exception as Ex;
|
||||
|
||||
final class File
|
||||
{
|
||||
/**
|
||||
* Encrypts the input file, saving the ciphertext to the output file.
|
||||
*
|
||||
* @param string $inputFilename
|
||||
* @param string $outputFilename
|
||||
* @param Key $key
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\IOException
|
||||
*/
|
||||
public static function encryptFile($inputFilename, $outputFilename, Key $key)
|
||||
{
|
||||
self::encryptFileInternal(
|
||||
$inputFilename,
|
||||
$outputFilename,
|
||||
KeyOrPassword::createFromKey($key)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a file with a password, using a slow key derivation function to
|
||||
* make password cracking more expensive.
|
||||
*
|
||||
* @param string $inputFilename
|
||||
* @param string $outputFilename
|
||||
* @param string $password
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\IOException
|
||||
*/
|
||||
public static function encryptFileWithPassword($inputFilename, $outputFilename, $password)
|
||||
{
|
||||
self::encryptFileInternal(
|
||||
$inputFilename,
|
||||
$outputFilename,
|
||||
KeyOrPassword::createFromPassword($password)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the input file, saving the plaintext to the output file.
|
||||
*
|
||||
* @param string $inputFilename
|
||||
* @param string $outputFilename
|
||||
* @param Key $key
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\IOException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*/
|
||||
public static function decryptFile($inputFilename, $outputFilename, Key $key)
|
||||
{
|
||||
self::decryptFileInternal(
|
||||
$inputFilename,
|
||||
$outputFilename,
|
||||
KeyOrPassword::createFromKey($key)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a file with a password, using a slow key derivation function to
|
||||
* make password cracking more expensive.
|
||||
*
|
||||
* @param string $inputFilename
|
||||
* @param string $outputFilename
|
||||
* @param string $password
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\IOException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*/
|
||||
public static function decryptFileWithPassword($inputFilename, $outputFilename, $password)
|
||||
{
|
||||
self::decryptFileInternal(
|
||||
$inputFilename,
|
||||
$outputFilename,
|
||||
KeyOrPassword::createFromPassword($password)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes two resource handles and encrypts the contents of the first,
|
||||
* writing the ciphertext into the second.
|
||||
*
|
||||
* @param resource $inputHandle
|
||||
* @param resource $outputHandle
|
||||
* @param Key $key
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*/
|
||||
public static function encryptResource($inputHandle, $outputHandle, Key $key)
|
||||
{
|
||||
self::encryptResourceInternal(
|
||||
$inputHandle,
|
||||
$outputHandle,
|
||||
KeyOrPassword::createFromKey($key)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the contents of one resource handle into another with a
|
||||
* password, using a slow key derivation function to make password cracking
|
||||
* more expensive.
|
||||
*
|
||||
* @param resource $inputHandle
|
||||
* @param resource $outputHandle
|
||||
* @param string $password
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\IOException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*/
|
||||
public static function encryptResourceWithPassword($inputHandle, $outputHandle, $password)
|
||||
{
|
||||
self::encryptResourceInternal(
|
||||
$inputHandle,
|
||||
$outputHandle,
|
||||
KeyOrPassword::createFromPassword($password)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes two resource handles and decrypts the contents of the first,
|
||||
* writing the plaintext into the second.
|
||||
*
|
||||
* @param resource $inputHandle
|
||||
* @param resource $outputHandle
|
||||
* @param Key $key
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\IOException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*/
|
||||
public static function decryptResource($inputHandle, $outputHandle, Key $key)
|
||||
{
|
||||
self::decryptResourceInternal(
|
||||
$inputHandle,
|
||||
$outputHandle,
|
||||
KeyOrPassword::createFromKey($key)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the contents of one resource into another with a password, using
|
||||
* a slow key derivation function to make password cracking more expensive.
|
||||
*
|
||||
* @param resource $inputHandle
|
||||
* @param resource $outputHandle
|
||||
* @param string $password
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\IOException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*/
|
||||
public static function decryptResourceWithPassword($inputHandle, $outputHandle, $password)
|
||||
{
|
||||
self::decryptResourceInternal(
|
||||
$inputHandle,
|
||||
$outputHandle,
|
||||
KeyOrPassword::createFromPassword($password)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a file with either a key or a password.
|
||||
*
|
||||
* @param string $inputFilename
|
||||
* @param string $outputFilename
|
||||
* @param KeyOrPassword $secret
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\CryptoException
|
||||
* @throws Ex\IOException
|
||||
*/
|
||||
private static function encryptFileInternal($inputFilename, $outputFilename, KeyOrPassword $secret)
|
||||
{
|
||||
/* Open the input file. */
|
||||
$if = @\fopen($inputFilename, 'rb');
|
||||
if ($if === false) {
|
||||
throw new Ex\IOException(
|
||||
'Cannot open input file for encrypting: ' .
|
||||
self::getLastErrorMessage()
|
||||
);
|
||||
}
|
||||
if (\is_callable('\\stream_set_read_buffer')) {
|
||||
/* This call can fail, but the only consequence is performance. */
|
||||
\stream_set_read_buffer($if, 0);
|
||||
}
|
||||
|
||||
/* Open the output file. */
|
||||
$of = @\fopen($outputFilename, 'wb');
|
||||
if ($of === false) {
|
||||
\fclose($if);
|
||||
throw new Ex\IOException(
|
||||
'Cannot open output file for encrypting: ' .
|
||||
self::getLastErrorMessage()
|
||||
);
|
||||
}
|
||||
if (\is_callable('\\stream_set_write_buffer')) {
|
||||
/* This call can fail, but the only consequence is performance. */
|
||||
\stream_set_write_buffer($of, 0);
|
||||
}
|
||||
|
||||
/* Perform the encryption. */
|
||||
try {
|
||||
self::encryptResourceInternal($if, $of, $secret);
|
||||
} catch (Ex\CryptoException $ex) {
|
||||
\fclose($if);
|
||||
\fclose($of);
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
/* Close the input file. */
|
||||
if (\fclose($if) === false) {
|
||||
\fclose($of);
|
||||
throw new Ex\IOException(
|
||||
'Cannot close input file after encrypting'
|
||||
);
|
||||
}
|
||||
|
||||
/* Close the output file. */
|
||||
if (\fclose($of) === false) {
|
||||
throw new Ex\IOException(
|
||||
'Cannot close output file after encrypting'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a file with either a key or a password.
|
||||
*
|
||||
* @param string $inputFilename
|
||||
* @param string $outputFilename
|
||||
* @param KeyOrPassword $secret
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\CryptoException
|
||||
* @throws Ex\IOException
|
||||
*/
|
||||
private static function decryptFileInternal($inputFilename, $outputFilename, KeyOrPassword $secret)
|
||||
{
|
||||
/* Open the input file. */
|
||||
$if = @\fopen($inputFilename, 'rb');
|
||||
if ($if === false) {
|
||||
throw new Ex\IOException(
|
||||
'Cannot open input file for decrypting: ' .
|
||||
self::getLastErrorMessage()
|
||||
);
|
||||
}
|
||||
|
||||
if (\is_callable('\\stream_set_read_buffer')) {
|
||||
/* This call can fail, but the only consequence is performance. */
|
||||
\stream_set_read_buffer($if, 0);
|
||||
}
|
||||
|
||||
/* Open the output file. */
|
||||
$of = @\fopen($outputFilename, 'wb');
|
||||
if ($of === false) {
|
||||
\fclose($if);
|
||||
throw new Ex\IOException(
|
||||
'Cannot open output file for decrypting: ' .
|
||||
self::getLastErrorMessage()
|
||||
);
|
||||
}
|
||||
|
||||
if (\is_callable('\\stream_set_write_buffer')) {
|
||||
/* This call can fail, but the only consequence is performance. */
|
||||
\stream_set_write_buffer($of, 0);
|
||||
}
|
||||
|
||||
/* Perform the decryption. */
|
||||
try {
|
||||
self::decryptResourceInternal($if, $of, $secret);
|
||||
} catch (Ex\CryptoException $ex) {
|
||||
\fclose($if);
|
||||
\fclose($of);
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
/* Close the input file. */
|
||||
if (\fclose($if) === false) {
|
||||
\fclose($of);
|
||||
throw new Ex\IOException(
|
||||
'Cannot close input file after decrypting'
|
||||
);
|
||||
}
|
||||
|
||||
/* Close the output file. */
|
||||
if (\fclose($of) === false) {
|
||||
throw new Ex\IOException(
|
||||
'Cannot close output file after decrypting'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a resource with either a key or a password.
|
||||
*
|
||||
* @param resource $inputHandle
|
||||
* @param resource $outputHandle
|
||||
* @param KeyOrPassword $secret
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\IOException
|
||||
*/
|
||||
private static function encryptResourceInternal($inputHandle, $outputHandle, KeyOrPassword $secret)
|
||||
{
|
||||
if (! \is_resource($inputHandle)) {
|
||||
throw new Ex\IOException(
|
||||
'Input handle must be a resource!'
|
||||
);
|
||||
}
|
||||
if (! \is_resource($outputHandle)) {
|
||||
throw new Ex\IOException(
|
||||
'Output handle must be a resource!'
|
||||
);
|
||||
}
|
||||
|
||||
$inputStat = \fstat($inputHandle);
|
||||
$inputSize = $inputStat['size'];
|
||||
|
||||
$file_salt = Core::secureRandom(Core::SALT_BYTE_SIZE);
|
||||
$keys = $secret->deriveKeys($file_salt);
|
||||
$ekey = $keys->getEncryptionKey();
|
||||
$akey = $keys->getAuthenticationKey();
|
||||
|
||||
$ivsize = Core::BLOCK_BYTE_SIZE;
|
||||
$iv = Core::secureRandom($ivsize);
|
||||
|
||||
/* Initialize a streaming HMAC state. */
|
||||
/** @var resource $hmac */
|
||||
$hmac = \hash_init(Core::HASH_FUNCTION_NAME, HASH_HMAC, $akey);
|
||||
if (!\is_resource($hmac)) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Cannot initialize a hash context'
|
||||
);
|
||||
}
|
||||
|
||||
/* Write the header, salt, and IV. */
|
||||
self::writeBytes(
|
||||
$outputHandle,
|
||||
Core::CURRENT_VERSION . $file_salt . $iv,
|
||||
Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE + $ivsize
|
||||
);
|
||||
|
||||
/* Add the header, salt, and IV to the HMAC. */
|
||||
\hash_update($hmac, Core::CURRENT_VERSION);
|
||||
\hash_update($hmac, $file_salt);
|
||||
\hash_update($hmac, $iv);
|
||||
|
||||
/* $thisIv will be incremented after each call to the encryption. */
|
||||
$thisIv = $iv;
|
||||
|
||||
/* How many blocks do we encrypt at a time? We increment by this value. */
|
||||
$inc = (int) (Core::BUFFER_BYTE_SIZE / Core::BLOCK_BYTE_SIZE);
|
||||
|
||||
/* Loop until we reach the end of the input file. */
|
||||
$at_file_end = false;
|
||||
while (! (\feof($inputHandle) || $at_file_end)) {
|
||||
/* Find out if we can read a full buffer, or only a partial one. */
|
||||
/** @var int */
|
||||
$pos = \ftell($inputHandle);
|
||||
if (!\is_int($pos)) {
|
||||
throw new Ex\IOException(
|
||||
'Could not get current position in input file during encryption'
|
||||
);
|
||||
}
|
||||
if ($pos + Core::BUFFER_BYTE_SIZE >= $inputSize) {
|
||||
/* We're at the end of the file, so we need to break out of the loop. */
|
||||
$at_file_end = true;
|
||||
$read = self::readBytes(
|
||||
$inputHandle,
|
||||
$inputSize - $pos
|
||||
);
|
||||
} else {
|
||||
$read = self::readBytes(
|
||||
$inputHandle,
|
||||
Core::BUFFER_BYTE_SIZE
|
||||
);
|
||||
}
|
||||
|
||||
/* Encrypt this buffer. */
|
||||
/** @var string */
|
||||
$encrypted = \openssl_encrypt(
|
||||
$read,
|
||||
Core::CIPHER_METHOD,
|
||||
$ekey,
|
||||
OPENSSL_RAW_DATA,
|
||||
$thisIv
|
||||
);
|
||||
|
||||
if (!\is_string($encrypted)) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'OpenSSL encryption error'
|
||||
);
|
||||
}
|
||||
|
||||
/* Write this buffer's ciphertext. */
|
||||
self::writeBytes($outputHandle, $encrypted, Core::ourStrlen($encrypted));
|
||||
/* Add this buffer's ciphertext to the HMAC. */
|
||||
\hash_update($hmac, $encrypted);
|
||||
|
||||
/* Increment the counter by the number of blocks in a buffer. */
|
||||
$thisIv = Core::incrementCounter($thisIv, $inc);
|
||||
/* WARNING: Usually, unless the file is a multiple of the buffer
|
||||
* size, $thisIv will contain an incorrect value here on the last
|
||||
* iteration of this loop. */
|
||||
}
|
||||
|
||||
/* Get the HMAC and append it to the ciphertext. */
|
||||
$final_mac = \hash_final($hmac, true);
|
||||
self::writeBytes($outputHandle, $final_mac, Core::MAC_BYTE_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts a file-backed resource with either a key or a password.
|
||||
*
|
||||
* @param resource $inputHandle
|
||||
* @param resource $outputHandle
|
||||
* @param KeyOrPassword $secret
|
||||
* @return void
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\IOException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*/
|
||||
public static function decryptResourceInternal($inputHandle, $outputHandle, KeyOrPassword $secret)
|
||||
{
|
||||
if (! \is_resource($inputHandle)) {
|
||||
throw new Ex\IOException(
|
||||
'Input handle must be a resource!'
|
||||
);
|
||||
}
|
||||
if (! \is_resource($outputHandle)) {
|
||||
throw new Ex\IOException(
|
||||
'Output handle must be a resource!'
|
||||
);
|
||||
}
|
||||
|
||||
/* Make sure the file is big enough for all the reads we need to do. */
|
||||
$stat = \fstat($inputHandle);
|
||||
if ($stat['size'] < Core::MINIMUM_CIPHERTEXT_SIZE) {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'Input file is too small to have been created by this library.'
|
||||
);
|
||||
}
|
||||
|
||||
/* Check the version header. */
|
||||
$header = self::readBytes($inputHandle, Core::HEADER_VERSION_SIZE);
|
||||
if ($header !== Core::CURRENT_VERSION) {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'Bad version header.'
|
||||
);
|
||||
}
|
||||
|
||||
/* Get the salt. */
|
||||
$file_salt = self::readBytes($inputHandle, Core::SALT_BYTE_SIZE);
|
||||
|
||||
/* Get the IV. */
|
||||
$ivsize = Core::BLOCK_BYTE_SIZE;
|
||||
$iv = self::readBytes($inputHandle, $ivsize);
|
||||
|
||||
/* Derive the authentication and encryption keys. */
|
||||
$keys = $secret->deriveKeys($file_salt);
|
||||
$ekey = $keys->getEncryptionKey();
|
||||
$akey = $keys->getAuthenticationKey();
|
||||
|
||||
/* We'll store the MAC of each buffer-sized chunk as we verify the
|
||||
* actual MAC, so that we can check them again when decrypting. */
|
||||
$macs = [];
|
||||
|
||||
/* $thisIv will be incremented after each call to the decryption. */
|
||||
$thisIv = $iv;
|
||||
|
||||
/* How many blocks do we encrypt at a time? We increment by this value. */
|
||||
$inc = (int) (Core::BUFFER_BYTE_SIZE / Core::BLOCK_BYTE_SIZE);
|
||||
|
||||
/* Get the HMAC. */
|
||||
if (\fseek($inputHandle, (-1 * Core::MAC_BYTE_SIZE), SEEK_END) === false) {
|
||||
throw new Ex\IOException(
|
||||
'Cannot seek to beginning of MAC within input file'
|
||||
);
|
||||
}
|
||||
|
||||
/* Get the position of the last byte in the actual ciphertext. */
|
||||
/** @var int $cipher_end */
|
||||
$cipher_end = \ftell($inputHandle);
|
||||
if (!\is_int($cipher_end)) {
|
||||
throw new Ex\IOException(
|
||||
'Cannot read input file'
|
||||
);
|
||||
}
|
||||
/* We have the position of the first byte of the HMAC. Go back by one. */
|
||||
--$cipher_end;
|
||||
|
||||
/* Read the HMAC. */
|
||||
/** @var string $stored_mac */
|
||||
$stored_mac = self::readBytes($inputHandle, Core::MAC_BYTE_SIZE);
|
||||
|
||||
/* Initialize a streaming HMAC state. */
|
||||
/** @var resource $hmac */
|
||||
$hmac = \hash_init(Core::HASH_FUNCTION_NAME, HASH_HMAC, $akey);
|
||||
if (!\is_resource($hmac)) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Cannot initialize a hash context'
|
||||
);
|
||||
}
|
||||
|
||||
/* Reset file pointer to the beginning of the file after the header */
|
||||
if (\fseek($inputHandle, Core::HEADER_VERSION_SIZE, SEEK_SET) === false) {
|
||||
throw new Ex\IOException(
|
||||
'Cannot read seek within input file'
|
||||
);
|
||||
}
|
||||
|
||||
/* Seek to the start of the actual ciphertext. */
|
||||
if (\fseek($inputHandle, Core::SALT_BYTE_SIZE + $ivsize, SEEK_CUR) === false) {
|
||||
throw new Ex\IOException(
|
||||
'Cannot seek input file to beginning of ciphertext'
|
||||
);
|
||||
}
|
||||
|
||||
/* PASS #1: Calculating the HMAC. */
|
||||
|
||||
\hash_update($hmac, $header);
|
||||
\hash_update($hmac, $file_salt);
|
||||
\hash_update($hmac, $iv);
|
||||
/** @var resource $hmac2 */
|
||||
$hmac2 = \hash_copy($hmac);
|
||||
|
||||
$break = false;
|
||||
while (! $break) {
|
||||
/** @var int $pos */
|
||||
$pos = \ftell($inputHandle);
|
||||
if (!\is_int($pos)) {
|
||||
throw new Ex\IOException(
|
||||
'Could not get current position in input file during decryption'
|
||||
);
|
||||
}
|
||||
|
||||
/* Read the next buffer-sized chunk (or less). */
|
||||
if ($pos + Core::BUFFER_BYTE_SIZE >= $cipher_end) {
|
||||
$break = true;
|
||||
$read = self::readBytes(
|
||||
$inputHandle,
|
||||
$cipher_end - $pos + 1
|
||||
);
|
||||
} else {
|
||||
$read = self::readBytes(
|
||||
$inputHandle,
|
||||
Core::BUFFER_BYTE_SIZE
|
||||
);
|
||||
}
|
||||
|
||||
/* Update the HMAC. */
|
||||
\hash_update($hmac, $read);
|
||||
|
||||
/* Remember this buffer-sized chunk's HMAC. */
|
||||
/** @var resource $chunk_mac */
|
||||
$chunk_mac = \hash_copy($hmac);
|
||||
if (!\is_resource($chunk_mac)) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Cannot duplicate a hash context'
|
||||
);
|
||||
}
|
||||
$macs []= \hash_final($chunk_mac);
|
||||
}
|
||||
|
||||
/* Get the final HMAC, which should match the stored one. */
|
||||
/** @var string $final_mac */
|
||||
$final_mac = \hash_final($hmac, true);
|
||||
|
||||
/* Verify the HMAC. */
|
||||
if (! Core::hashEquals($final_mac, $stored_mac)) {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'Integrity check failed.'
|
||||
);
|
||||
}
|
||||
|
||||
/* PASS #2: Decrypt and write output. */
|
||||
|
||||
/* Rewind to the start of the actual ciphertext. */
|
||||
if (\fseek($inputHandle, Core::SALT_BYTE_SIZE + $ivsize + Core::HEADER_VERSION_SIZE, SEEK_SET) === false) {
|
||||
throw new Ex\IOException(
|
||||
'Could not move the input file pointer during decryption'
|
||||
);
|
||||
}
|
||||
|
||||
$at_file_end = false;
|
||||
while (! $at_file_end) {
|
||||
/** @var int $pos */
|
||||
$pos = \ftell($inputHandle);
|
||||
if (!\is_int($pos)) {
|
||||
throw new Ex\IOException(
|
||||
'Could not get current position in input file during decryption'
|
||||
);
|
||||
}
|
||||
|
||||
/* Read the next buffer-sized chunk (or less). */
|
||||
if ($pos + Core::BUFFER_BYTE_SIZE >= $cipher_end) {
|
||||
$at_file_end = true;
|
||||
$read = self::readBytes(
|
||||
$inputHandle,
|
||||
$cipher_end - $pos + 1
|
||||
);
|
||||
} else {
|
||||
$read = self::readBytes(
|
||||
$inputHandle,
|
||||
Core::BUFFER_BYTE_SIZE
|
||||
);
|
||||
}
|
||||
|
||||
/* Recalculate the MAC (so far) and compare it with the one we
|
||||
* remembered from pass #1 to ensure attackers didn't change the
|
||||
* ciphertext after MAC verification. */
|
||||
\hash_update($hmac2, $read);
|
||||
/** @var resource $calc_mac */
|
||||
$calc_mac = \hash_copy($hmac2);
|
||||
if (!\is_resource($calc_mac)) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Cannot duplicate a hash context'
|
||||
);
|
||||
}
|
||||
$calc = \hash_final($calc_mac);
|
||||
|
||||
if (empty($macs)) {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'File was modified after MAC verification'
|
||||
);
|
||||
} elseif (! Core::hashEquals(\array_shift($macs), $calc)) {
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
'File was modified after MAC verification'
|
||||
);
|
||||
}
|
||||
|
||||
/* Decrypt this buffer-sized chunk. */
|
||||
/** @var string $decrypted */
|
||||
$decrypted = \openssl_decrypt(
|
||||
$read,
|
||||
Core::CIPHER_METHOD,
|
||||
$ekey,
|
||||
OPENSSL_RAW_DATA,
|
||||
$thisIv
|
||||
);
|
||||
if (!\is_string($decrypted)) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'OpenSSL decryption error'
|
||||
);
|
||||
}
|
||||
|
||||
/* Write the plaintext to the output file. */
|
||||
self::writeBytes(
|
||||
$outputHandle,
|
||||
$decrypted,
|
||||
Core::ourStrlen($decrypted)
|
||||
);
|
||||
|
||||
/* Increment the IV by the amount of blocks in a buffer. */
|
||||
/** @var string $thisIv */
|
||||
$thisIv = Core::incrementCounter($thisIv, $inc);
|
||||
/* WARNING: Usually, unless the file is a multiple of the buffer
|
||||
* size, $thisIv will contain an incorrect value here on the last
|
||||
* iteration of this loop. */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from a stream; prevent partial reads.
|
||||
*
|
||||
* @param resource $stream
|
||||
* @param int $num_bytes
|
||||
* @return string
|
||||
*
|
||||
* @throws Ex\IOException
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function readBytes($stream, $num_bytes)
|
||||
{
|
||||
if ($num_bytes < 0) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Tried to read less than 0 bytes'
|
||||
);
|
||||
} elseif ($num_bytes === 0) {
|
||||
return '';
|
||||
}
|
||||
$buf = '';
|
||||
$remaining = $num_bytes;
|
||||
while ($remaining > 0 && ! \feof($stream)) {
|
||||
/** @var string $read */
|
||||
$read = \fread($stream, $remaining);
|
||||
if (!\is_string($read)) {
|
||||
throw new Ex\IOException(
|
||||
'Could not read from the file'
|
||||
);
|
||||
}
|
||||
$buf .= $read;
|
||||
$remaining -= Core::ourStrlen($read);
|
||||
}
|
||||
if (Core::ourStrlen($buf) !== $num_bytes) {
|
||||
throw new Ex\IOException(
|
||||
'Tried to read past the end of the file'
|
||||
);
|
||||
}
|
||||
return $buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to a stream; prevents partial writes.
|
||||
*
|
||||
* @param resource $stream
|
||||
* @param string $buf
|
||||
* @param int $num_bytes
|
||||
* @return int
|
||||
*
|
||||
* @throws Ex\IOException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function writeBytes($stream, $buf, $num_bytes = null)
|
||||
{
|
||||
$bufSize = Core::ourStrlen($buf);
|
||||
if ($num_bytes === null) {
|
||||
$num_bytes = $bufSize;
|
||||
}
|
||||
if ($num_bytes > $bufSize) {
|
||||
throw new Ex\IOException(
|
||||
'Trying to write more bytes than the buffer contains.'
|
||||
);
|
||||
}
|
||||
if ($num_bytes < 0) {
|
||||
throw new Ex\IOException(
|
||||
'Tried to write less than 0 bytes'
|
||||
);
|
||||
}
|
||||
$remaining = $num_bytes;
|
||||
while ($remaining > 0) {
|
||||
/** @var int $written */
|
||||
$written = \fwrite($stream, $buf, $remaining);
|
||||
if (!\is_int($written)) {
|
||||
throw new Ex\IOException(
|
||||
'Could not write to the file'
|
||||
);
|
||||
}
|
||||
$buf = (string) Core::ourSubstr($buf, $written, null);
|
||||
$remaining -= $written;
|
||||
}
|
||||
return $num_bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last PHP error's or warning's message string.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function getLastErrorMessage()
|
||||
{
|
||||
$error = error_get_last();
|
||||
if ($error === null) {
|
||||
return '[no PHP error]';
|
||||
} else {
|
||||
return $error['message'];
|
||||
}
|
||||
}
|
||||
}
|
||||
95
administrator/components/com_jce/vendor/Defuse/Crypto/Key.php
vendored
Normal file
95
administrator/components/com_jce/vendor/Defuse/Crypto/Key.php
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto;
|
||||
|
||||
use Defuse\Crypto\Exception as Ex;
|
||||
|
||||
final class Key
|
||||
{
|
||||
const KEY_CURRENT_VERSION = "\xDE\xF0\x00\x00";
|
||||
const KEY_BYTE_SIZE = 32;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $key_bytes;
|
||||
|
||||
/**
|
||||
* Creates new random key.
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return Key
|
||||
*/
|
||||
public static function createNewRandomKey()
|
||||
{
|
||||
return new Key(Core::secureRandom(self::KEY_BYTE_SIZE));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a Key from its encoded form.
|
||||
*
|
||||
* By default, this function will call Encoding::trimTrailingWhitespace()
|
||||
* to remove trailing CR, LF, NUL, TAB, and SPACE characters, which are
|
||||
* commonly appended to files when working with text editors.
|
||||
*
|
||||
* @param string $saved_key_string
|
||||
* @param bool $do_not_trim (default: false)
|
||||
*
|
||||
* @throws Ex\BadFormatException
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return Key
|
||||
*/
|
||||
public static function loadFromAsciiSafeString($saved_key_string, $do_not_trim = false)
|
||||
{
|
||||
if (!$do_not_trim) {
|
||||
$saved_key_string = Encoding::trimTrailingWhitespace($saved_key_string);
|
||||
}
|
||||
$key_bytes = Encoding::loadBytesFromChecksummedAsciiSafeString(self::KEY_CURRENT_VERSION, $saved_key_string);
|
||||
return new Key($key_bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the Key into a string of printable ASCII characters.
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function saveToAsciiSafeString()
|
||||
{
|
||||
return Encoding::saveBytesToChecksummedAsciiSafeString(
|
||||
self::KEY_CURRENT_VERSION,
|
||||
$this->key_bytes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the raw bytes of the key.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRawBytes()
|
||||
{
|
||||
return $this->key_bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new Key object from a string of raw bytes.
|
||||
*
|
||||
* @param string $bytes
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*/
|
||||
private function __construct($bytes)
|
||||
{
|
||||
if (Core::ourStrlen($bytes) !== self::KEY_BYTE_SIZE) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Bad key length.'
|
||||
);
|
||||
}
|
||||
$this->key_bytes = $bytes;
|
||||
}
|
||||
|
||||
}
|
||||
133
administrator/components/com_jce/vendor/Defuse/Crypto/KeyOrPassword.php
vendored
Normal file
133
administrator/components/com_jce/vendor/Defuse/Crypto/KeyOrPassword.php
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto;
|
||||
|
||||
use Defuse\Crypto\Exception as Ex;
|
||||
|
||||
final class KeyOrPassword
|
||||
{
|
||||
const PBKDF2_ITERATIONS = 100000;
|
||||
const SECRET_TYPE_KEY = 1;
|
||||
const SECRET_TYPE_PASSWORD = 2;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $secret_type = 0;
|
||||
|
||||
/**
|
||||
* @var Key|string
|
||||
*/
|
||||
private $secret;
|
||||
|
||||
/**
|
||||
* Initializes an instance of KeyOrPassword from a key.
|
||||
*
|
||||
* @param Key $key
|
||||
*
|
||||
* @return KeyOrPassword
|
||||
*/
|
||||
public static function createFromKey(Key $key)
|
||||
{
|
||||
return new KeyOrPassword(self::SECRET_TYPE_KEY, $key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes an instance of KeyOrPassword from a password.
|
||||
*
|
||||
* @param string $password
|
||||
*
|
||||
* @return KeyOrPassword
|
||||
*/
|
||||
public static function createFromPassword($password)
|
||||
{
|
||||
return new KeyOrPassword(self::SECRET_TYPE_PASSWORD, $password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives authentication and encryption keys from the secret, using a slow
|
||||
* key derivation function if the secret is a password.
|
||||
*
|
||||
* @param string $salt
|
||||
*
|
||||
* @throws Ex\CryptoException
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return DerivedKeys
|
||||
*/
|
||||
public function deriveKeys($salt)
|
||||
{
|
||||
if (Core::ourStrlen($salt) !== Core::SALT_BYTE_SIZE) {
|
||||
throw new Ex\EnvironmentIsBrokenException('Bad salt.');
|
||||
}
|
||||
|
||||
if ($this->secret_type === self::SECRET_TYPE_KEY) {
|
||||
if (!($this->secret instanceof Key)) {
|
||||
throw new Ex\CryptoException('Expected a Key object');
|
||||
}
|
||||
$akey = Core::HKDF(
|
||||
Core::HASH_FUNCTION_NAME,
|
||||
$this->secret->getRawBytes(),
|
||||
Core::KEY_BYTE_SIZE,
|
||||
Core::AUTHENTICATION_INFO_STRING,
|
||||
$salt
|
||||
);
|
||||
$ekey = Core::HKDF(
|
||||
Core::HASH_FUNCTION_NAME,
|
||||
$this->secret->getRawBytes(),
|
||||
Core::KEY_BYTE_SIZE,
|
||||
Core::ENCRYPTION_INFO_STRING,
|
||||
$salt
|
||||
);
|
||||
return new DerivedKeys($akey, $ekey);
|
||||
} elseif ($this->secret_type === self::SECRET_TYPE_PASSWORD) {
|
||||
if (!\is_string($this->secret)) {
|
||||
throw new Ex\CryptoException('Expected a string');
|
||||
}
|
||||
/* Our PBKDF2 polyfill is vulnerable to a DoS attack documented in
|
||||
* GitHub issue #230. The fix is to pre-hash the password to ensure
|
||||
* it is short. We do the prehashing here instead of in pbkdf2() so
|
||||
* that pbkdf2() still computes the function as defined by the
|
||||
* standard. */
|
||||
$prehash = \hash(Core::HASH_FUNCTION_NAME, $this->secret, true);
|
||||
$prekey = Core::pbkdf2(
|
||||
Core::HASH_FUNCTION_NAME,
|
||||
$prehash,
|
||||
$salt,
|
||||
self::PBKDF2_ITERATIONS,
|
||||
Core::KEY_BYTE_SIZE,
|
||||
true
|
||||
);
|
||||
$akey = Core::HKDF(
|
||||
Core::HASH_FUNCTION_NAME,
|
||||
$prekey,
|
||||
Core::KEY_BYTE_SIZE,
|
||||
Core::AUTHENTICATION_INFO_STRING,
|
||||
$salt
|
||||
);
|
||||
/* Note the cryptographic re-use of $salt here. */
|
||||
$ekey = Core::HKDF(
|
||||
Core::HASH_FUNCTION_NAME,
|
||||
$prekey,
|
||||
Core::KEY_BYTE_SIZE,
|
||||
Core::ENCRYPTION_INFO_STRING,
|
||||
$salt
|
||||
);
|
||||
return new DerivedKeys($akey, $ekey);
|
||||
} else {
|
||||
throw new Ex\EnvironmentIsBrokenException('Bad secret type.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for KeyOrPassword.
|
||||
*
|
||||
* @param int $secret_type
|
||||
* @param mixed $secret (either a Key or a password string)
|
||||
*/
|
||||
private function __construct($secret_type, $secret)
|
||||
{
|
||||
$this->secret_type = $secret_type;
|
||||
$this->secret = $secret;
|
||||
}
|
||||
}
|
||||
116
administrator/components/com_jce/vendor/Defuse/Crypto/KeyProtectedByPassword.php
vendored
Normal file
116
administrator/components/com_jce/vendor/Defuse/Crypto/KeyProtectedByPassword.php
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto;
|
||||
|
||||
use Defuse\Crypto\Exception as Ex;
|
||||
|
||||
final class KeyProtectedByPassword
|
||||
{
|
||||
const PASSWORD_KEY_CURRENT_VERSION = "\xDE\xF1\x00\x00";
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $encrypted_key = '';
|
||||
|
||||
/**
|
||||
* Creates a random key protected by the provided password.
|
||||
*
|
||||
* @param string $password
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return KeyProtectedByPassword
|
||||
*/
|
||||
public static function createRandomPasswordProtectedKey($password)
|
||||
{
|
||||
$inner_key = Key::createNewRandomKey();
|
||||
/* The password is hashed as a form of poor-man's domain separation
|
||||
* between this use of encryptWithPassword() and other uses of
|
||||
* encryptWithPassword() that the user may also be using as part of the
|
||||
* same protocol. */
|
||||
$encrypted_key = Crypto::encryptWithPassword(
|
||||
$inner_key->saveToAsciiSafeString(),
|
||||
\hash(Core::HASH_FUNCTION_NAME, $password, true),
|
||||
true
|
||||
);
|
||||
|
||||
return new KeyProtectedByPassword($encrypted_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a KeyProtectedByPassword from its encoded form.
|
||||
*
|
||||
* @param string $saved_key_string
|
||||
*
|
||||
* @throws Ex\BadFormatException
|
||||
*
|
||||
* @return KeyProtectedByPassword
|
||||
*/
|
||||
public static function loadFromAsciiSafeString($saved_key_string)
|
||||
{
|
||||
$encrypted_key = Encoding::loadBytesFromChecksummedAsciiSafeString(
|
||||
self::PASSWORD_KEY_CURRENT_VERSION,
|
||||
$saved_key_string
|
||||
);
|
||||
return new KeyProtectedByPassword($encrypted_key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes the KeyProtectedByPassword into a string of printable ASCII
|
||||
* characters.
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function saveToAsciiSafeString()
|
||||
{
|
||||
return Encoding::saveBytesToChecksummedAsciiSafeString(
|
||||
self::PASSWORD_KEY_CURRENT_VERSION,
|
||||
$this->encrypted_key
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the protected key, returning an unprotected Key object that can
|
||||
* be used for encryption and decryption.
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @throws Ex\WrongKeyOrModifiedCiphertextException
|
||||
*
|
||||
* @param string $password
|
||||
* @return Key
|
||||
*/
|
||||
public function unlockKey($password)
|
||||
{
|
||||
try {
|
||||
$inner_key_encoded = Crypto::decryptWithPassword(
|
||||
$this->encrypted_key,
|
||||
\hash(Core::HASH_FUNCTION_NAME, $password, true),
|
||||
true
|
||||
);
|
||||
return Key::loadFromAsciiSafeString($inner_key_encoded);
|
||||
} catch (Ex\BadFormatException $ex) {
|
||||
/* This should never happen unless an attacker replaced the
|
||||
* encrypted key ciphertext with some other ciphertext that was
|
||||
* encrypted with the same password. We transform the exception type
|
||||
* here in order to make the API simpler, avoiding the need to
|
||||
* document that this method might throw an Ex\BadFormatException. */
|
||||
throw new Ex\WrongKeyOrModifiedCiphertextException(
|
||||
"The decrypted key was found to be in an invalid format. " .
|
||||
"This very likely indicates it was modified by an attacker."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for KeyProtectedByPassword.
|
||||
*
|
||||
* @param string $encrypted_key
|
||||
*/
|
||||
private function __construct($encrypted_key)
|
||||
{
|
||||
$this->encrypted_key = $encrypted_key;
|
||||
}
|
||||
}
|
||||
247
administrator/components/com_jce/vendor/Defuse/Crypto/RuntimeTests.php
vendored
Normal file
247
administrator/components/com_jce/vendor/Defuse/Crypto/RuntimeTests.php
vendored
Normal file
@@ -0,0 +1,247 @@
|
||||
<?php
|
||||
|
||||
namespace Defuse\Crypto;
|
||||
|
||||
use Defuse\Crypto\Exception as Ex;
|
||||
|
||||
/*
|
||||
* We're using static class inheritance to get access to protected methods
|
||||
* inside Crypto. To make it easy to know where the method we're calling can be
|
||||
* found, within this file, prefix calls with `Crypto::` or `RuntimeTests::`,
|
||||
* and don't use `self::`.
|
||||
*/
|
||||
|
||||
class RuntimeTests extends Crypto
|
||||
{
|
||||
/**
|
||||
* Runs the runtime tests.
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @return void
|
||||
*/
|
||||
public static function runtimeTest()
|
||||
{
|
||||
// 0: Tests haven't been run yet.
|
||||
// 1: Tests have passed.
|
||||
// 2: Tests are running right now.
|
||||
// 3: Tests have failed.
|
||||
static $test_state = 0;
|
||||
|
||||
if ($test_state === 1 || $test_state === 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($test_state === 3) {
|
||||
/* If an intermittent problem caused a test to fail previously, we
|
||||
* want that to be indicated to the user with every call to this
|
||||
* library. This way, if the user first does something they really
|
||||
* don't care about, and just ignores all exceptions, they won't get
|
||||
* screwed when they then start to use the library for something
|
||||
* they do care about. */
|
||||
throw new Ex\EnvironmentIsBrokenException('Tests failed previously.');
|
||||
}
|
||||
|
||||
try {
|
||||
$test_state = 2;
|
||||
|
||||
Core::ensureFunctionExists('openssl_get_cipher_methods');
|
||||
if (\in_array(Core::CIPHER_METHOD, \openssl_get_cipher_methods()) === false) {
|
||||
throw new Ex\EnvironmentIsBrokenException(
|
||||
'Cipher method not supported. This is normally caused by an outdated ' .
|
||||
'version of OpenSSL (and/or OpenSSL compiled for FIPS compliance). ' .
|
||||
'Please upgrade to a newer version of OpenSSL that supports ' .
|
||||
Core::CIPHER_METHOD . ' to use this library.'
|
||||
);
|
||||
}
|
||||
|
||||
RuntimeTests::AESTestVector();
|
||||
RuntimeTests::HMACTestVector();
|
||||
RuntimeTests::HKDFTestVector();
|
||||
|
||||
RuntimeTests::testEncryptDecrypt();
|
||||
if (Core::ourStrlen(Key::createNewRandomKey()->getRawBytes()) != Core::KEY_BYTE_SIZE) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
|
||||
if (Core::ENCRYPTION_INFO_STRING == Core::AUTHENTICATION_INFO_STRING) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
} catch (Ex\EnvironmentIsBrokenException $ex) {
|
||||
// Do this, otherwise it will stay in the "tests are running" state.
|
||||
$test_state = 3;
|
||||
throw $ex;
|
||||
}
|
||||
|
||||
// Change this to '0' make the tests always re-run (for benchmarking).
|
||||
$test_state = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* High-level tests of Crypto operations.
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @return void
|
||||
*/
|
||||
private static function testEncryptDecrypt()
|
||||
{
|
||||
$key = Key::createNewRandomKey();
|
||||
$data = "EnCrYpT EvErYThInG\x00\x00";
|
||||
|
||||
// Make sure encrypting then decrypting doesn't change the message.
|
||||
$ciphertext = Crypto::encrypt($data, $key, true);
|
||||
try {
|
||||
$decrypted = Crypto::decrypt($ciphertext, $key, true);
|
||||
} catch (Ex\WrongKeyOrModifiedCiphertextException $ex) {
|
||||
// It's important to catch this and change it into a
|
||||
// Ex\EnvironmentIsBrokenException, otherwise a test failure could trick
|
||||
// the user into thinking it's just an invalid ciphertext!
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
if ($decrypted !== $data) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
|
||||
// Modifying the ciphertext: Appending a string.
|
||||
try {
|
||||
Crypto::decrypt($ciphertext . 'a', $key, true);
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
} catch (Ex\WrongKeyOrModifiedCiphertextException $e) { /* expected */
|
||||
}
|
||||
|
||||
// Modifying the ciphertext: Changing an HMAC byte.
|
||||
$indices_to_change = [
|
||||
0, // The header.
|
||||
Core::HEADER_VERSION_SIZE + 1, // the salt
|
||||
Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE + 1, // the IV
|
||||
Core::HEADER_VERSION_SIZE + Core::SALT_BYTE_SIZE + Core::BLOCK_BYTE_SIZE + 1, // the ciphertext
|
||||
];
|
||||
|
||||
foreach ($indices_to_change as $index) {
|
||||
try {
|
||||
$ciphertext[$index] = \chr((\ord($ciphertext[$index]) + 1) % 256);
|
||||
Crypto::decrypt($ciphertext, $key, true);
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
} catch (Ex\WrongKeyOrModifiedCiphertextException $e) { /* expected */
|
||||
}
|
||||
}
|
||||
|
||||
// Decrypting with the wrong key.
|
||||
$key = Key::createNewRandomKey();
|
||||
$data = 'abcdef';
|
||||
$ciphertext = Crypto::encrypt($data, $key, true);
|
||||
$wrong_key = Key::createNewRandomKey();
|
||||
try {
|
||||
Crypto::decrypt($ciphertext, $wrong_key, true);
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
} catch (Ex\WrongKeyOrModifiedCiphertextException $e) { /* expected */
|
||||
}
|
||||
|
||||
// Ciphertext too small.
|
||||
$key = Key::createNewRandomKey();
|
||||
$ciphertext = \str_repeat('A', Core::MINIMUM_CIPHERTEXT_SIZE - 1);
|
||||
try {
|
||||
Crypto::decrypt($ciphertext, $key, true);
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
} catch (Ex\WrongKeyOrModifiedCiphertextException $e) { /* expected */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test HKDF against test vectors.
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @return void
|
||||
*/
|
||||
private static function HKDFTestVector()
|
||||
{
|
||||
// HKDF test vectors from RFC 5869
|
||||
|
||||
// Test Case 1
|
||||
$ikm = \str_repeat("\x0b", 22);
|
||||
$salt = Encoding::hexToBin('000102030405060708090a0b0c');
|
||||
$info = Encoding::hexToBin('f0f1f2f3f4f5f6f7f8f9');
|
||||
$length = 42;
|
||||
$okm = Encoding::hexToBin(
|
||||
'3cb25f25faacd57a90434f64d0362f2a' .
|
||||
'2d2d0a90cf1a5a4c5db02d56ecc4c5bf' .
|
||||
'34007208d5b887185865'
|
||||
);
|
||||
$computed_okm = Core::HKDF('sha256', $ikm, $length, $info, $salt);
|
||||
if ($computed_okm !== $okm) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
|
||||
// Test Case 7
|
||||
$ikm = \str_repeat("\x0c", 22);
|
||||
$length = 42;
|
||||
$okm = Encoding::hexToBin(
|
||||
'2c91117204d745f3500d636a62f64f0a' .
|
||||
'b3bae548aa53d423b0d1f27ebba6f5e5' .
|
||||
'673a081d70cce7acfc48'
|
||||
);
|
||||
$computed_okm = Core::HKDF('sha1', $ikm, $length, '', null);
|
||||
if ($computed_okm !== $okm) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test HMAC against test vectors.
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @return void
|
||||
*/
|
||||
private static function HMACTestVector()
|
||||
{
|
||||
// HMAC test vector From RFC 4231 (Test Case 1)
|
||||
$key = \str_repeat("\x0b", 20);
|
||||
$data = 'Hi There';
|
||||
$correct = 'b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7';
|
||||
if (\hash_hmac(Core::HASH_FUNCTION_NAME, $data, $key) !== $correct) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test AES against test vectors.
|
||||
*
|
||||
* @throws Ex\EnvironmentIsBrokenException
|
||||
* @return void
|
||||
*/
|
||||
private static function AESTestVector()
|
||||
{
|
||||
// AES CTR mode test vector from NIST SP 800-38A
|
||||
$key = Encoding::hexToBin(
|
||||
'603deb1015ca71be2b73aef0857d7781' .
|
||||
'1f352c073b6108d72d9810a30914dff4'
|
||||
);
|
||||
$iv = Encoding::hexToBin('f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff');
|
||||
$plaintext = Encoding::hexToBin(
|
||||
'6bc1bee22e409f96e93d7e117393172a' .
|
||||
'ae2d8a571e03ac9c9eb76fac45af8e51' .
|
||||
'30c81c46a35ce411e5fbc1191a0a52ef' .
|
||||
'f69f2445df4f9b17ad2b417be66c3710'
|
||||
);
|
||||
$ciphertext = Encoding::hexToBin(
|
||||
'601ec313775789a5b7a7f504bbf3d228' .
|
||||
'f443e3ca4d62b59aca84e990cacaf5c5' .
|
||||
'2b0930daa23de94ce87017ba2d84988d' .
|
||||
'dfc9c58db67aada613c2dd08457941a6'
|
||||
);
|
||||
|
||||
$computed_ciphertext = Crypto::plainEncrypt($plaintext, $key, $iv);
|
||||
if ($computed_ciphertext !== $ciphertext) {
|
||||
echo \str_repeat("\n", 30);
|
||||
echo \bin2hex($computed_ciphertext);
|
||||
echo "\n---\n";
|
||||
echo \bin2hex($ciphertext);
|
||||
echo \str_repeat("\n", 30);
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
|
||||
$computed_plaintext = Crypto::plainDecrypt($ciphertext, $key, $iv, Core::CIPHER_METHOD);
|
||||
if ($computed_plaintext !== $plaintext) {
|
||||
throw new Ex\EnvironmentIsBrokenException();
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user