shell bypass 403
<?php
/**
* Joomla! Content Management System
*
* @copyright (C) 2023 Open Source Matters, Inc. <https://www.joomla.org>
* @license GNU General Public License version 2 or later; see LICENSE.txt
*/
namespace Joomla\CMS\Form\Field;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
use Joomla\CMS\Factory;
use Joomla\CMS\Form\FormField;
use Joomla\Database\ParameterType;
/**
* Provides a modal content selection
*
* @since 5.0.0
*/
class ModalSelectField extends FormField
{
/**
* The form field type.
*
* @var string
* @since 5.0.0
*/
protected $type = 'ModalSelect';
/**
* Layout to render
*
* @var string
* @since 5.0.0
*/
protected $layout = 'joomla.form.field.modal-select';
/**
* Enabled actions: select, clear, edit, new
*
* @var boolean[]
* @since 5.0.0
*/
protected $canDo = [];
/**
* Urls for modal: select, edit, new
*
* @var string[]
* @since 5.0.0
*/
protected $urls = [];
/**
* List of titles for each modal type: select, edit, new
*
* @var string[]
* @since 5.0.0
*/
protected $modalTitles = [];
/**
* List of icons for each button type: select, edit, new
*
* @var string[]
* @since 5.0.0
*/
protected $buttonIcons = [];
/**
* The table name to select the title related to the field value.
*
* @var string
* @since 5.2.0
*/
protected $sql_title_table = '';
/**
* The column name in the $sql_title_table, to select the title related to the field value.
*
* @var string
* @since 5.2.0
*/
protected $sql_title_column = '';
/**
* The key name in the $sql_title_table that represent the field value, to select the title related to the field value.
*
* @var string
* @since 5.2.0
*/
protected $sql_title_key = '';
/**
* Method to attach a Form 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.
*
* @return boolean True on success.
*
* @see FormField::setup()
* @since 5.0.0
*/
public function setup(\SimpleXMLElement $element, $value, $group = null)
{
$result = parent::setup($element, $value, $group);
if (!$result) {
return $result;
}
// Prepare enabled actions
$this->__set('select', (string) $this->element['select'] != 'false');
$this->__set('new', (string) $this->element['new'] == 'true');
$this->__set('edit', (string) $this->element['edit'] == 'true');
$this->__set('clear', (string) $this->element['clear'] != 'false');
// Prepare Urls and titles
foreach (
['urlSelect', 'urlNew', 'urlEdit', 'urlCheckin', 'titleSelect', 'titleNew', 'titleEdit', 'iconSelect',
'sql_title_table', 'sql_title_column', 'sql_title_key',] as $attr
) {
$this->__set($attr, (string) $this->element[$attr]);
}
return $result;
}
/**
* 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 5.0.0
*/
public function __get($name)
{
switch ($name) {
case 'select':
return $this->canDo['select'] ?? true;
case 'new':
return $this->canDo['new'] ?? false;
case 'edit':
return $this->canDo['edit'] ?? false;
case 'clear':
return $this->canDo['clear'] ?? true;
case 'urlSelect':
return $this->urls['select'] ?? '';
case 'urlNew':
return $this->urls['new'] ?? '';
case 'urlEdit':
return $this->urls['edit'] ?? '';
case 'urlCheckin':
return $this->urls['checkin'] ?? '';
case 'titleSelect':
return $this->modalTitles['select'] ?? '';
case 'titleNew':
return $this->modalTitles['new'] ?? '';
case 'titleEdit':
return $this->modalTitles['edit'] ?? '';
case 'iconSelect':
return $this->buttonIcons['select'] ?? '';
case 'sql_title_table':
case 'sql_title_column':
case 'sql_title_key':
return $this->$name;
default:
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 5.0.0
*/
public function __set($name, $value)
{
switch ($name) {
case 'select':
$this->canDo['select'] = (bool) $value;
break;
case 'new':
$this->canDo['new'] = (bool) $value;
break;
case 'edit':
$this->canDo['edit'] = (bool) $value;
break;
case 'clear':
$this->canDo['clear'] = (bool) $value;
break;
case 'urlSelect':
$this->urls['select'] = (string) $value;
break;
case 'urlNew':
$this->urls['new'] = (string) $value;
break;
case 'urlEdit':
$this->urls['edit'] = (string) $value;
break;
case 'urlCheckin':
$this->urls['checkin'] = (string) $value;
break;
case 'titleSelect':
$this->modalTitles['select'] = (string) $value;
break;
case 'titleNew':
$this->modalTitles['new'] = (string) $value;
break;
case 'titleEdit':
$this->modalTitles['edit'] = (string) $value;
break;
case 'iconSelect':
$this->buttonIcons['select'] = (string) $value;
break;
case 'sql_title_table':
case 'sql_title_column':
case 'sql_title_key':
$this->$name = (string) $value;
break;
default:
parent::__set($name, $value);
}
}
/**
* Method to get the field input markup.
*
* @return string The field input markup.
*
* @since 5.0.0
*/
protected function getInput()
{
if (empty($this->layout)) {
throw new \UnexpectedValueException(\sprintf('%s has no layout assigned.', $this->name));
}
// Get the layout data
$data = $this->collectLayoutData();
// Load the content title here to avoid a double DB Query
$data['valueTitle'] = $this->getValueTitle();
return $this->getRenderer($this->layout)->render($data);
}
/**
* Method to retrieve the title of selected item.
*
* @return string
*
* @since 5.0.0
*/
protected function getValueTitle()
{
// Selecting the title for the field value, when required info were given
if ($this->value && $this->sql_title_table && $this->sql_title_column && $this->sql_title_key) {
try {
$db = $this->getDatabase();
$query = $db->getQuery(true)
->select($db->quoteName($this->sql_title_column))
->from($db->quoteName($this->sql_title_table))
->where($db->quoteName($this->sql_title_key) . ' = :value')
->bind(':value', $this->value, ParameterType::INTEGER);
$db->setQuery($query);
return $db->loadResult() ?: $this->value;
} catch (\Throwable $e) {
Factory::getApplication()->enqueueMessage($e->getMessage(), 'error');
}
}
return $this->value;
}
/**
* Method to get the data to be passed to the layout for rendering.
*
* @return array
*
* @since 5.0.0
*/
protected function getLayoutData()
{
$data = parent::getLayoutData();
$data['canDo'] = $this->canDo;
$data['urls'] = $this->urls;
$data['modalTitles'] = $this->modalTitles;
$data['buttonIcons'] = $this->buttonIcons;
return $data;
}
}