uawdijnntqw1x1x1
IP : 216.73.216.231
Hostname : 213-108-241-110.cprapid.com
Kernel : Linux 213-108-241-110.cprapid.com 5.14.0-570.25.1.el9_6.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Jul 9 04:57:09 EDT 2025 x86_64
Disable Function : None :)
OS : Linux
PATH:
/
home
/
digilove
/
public_html
/
cache
/
.
/
..
/
41423
/
com_privacy.tar
/
/
controllers/consents.php000064400000004172152325744620011475 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Consents management controller class. * * @since 3.9.0 */ class PrivacyControllerConsents extends JControllerForm { /** * Method to invalidate specific consents. * * @return boolean * * @since 3.9.0 */ public function invalidate($key = null, $urlVar = null) { // Check for request forgeries JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); $ids = (array) $this->input->get('cid', array(), 'int'); // Remove zero values resulting from input filter $ids = array_filter($ids); if (empty($ids)) { $message = JText::_('JERROR_NO_ITEMS_SELECTED'); $this->setError($message); } else { // Get the model. /** @var PrivacyModelConsents $model */ $model = $this->getModel(); // Publish the items. if (!$model->invalidate($ids)) { $this->setError($model->getError()); } $message = JText::plural('COM_PRIVACY_N_CONSENTS_INVALIDATED', count($ids)); } $this->setRedirect(JRoute::_('index.php?option=com_privacy&view=consents', false), $message); } /** * Method to invalidate all consents of a specific subject. * * @return boolean * * @since 3.9.0 */ public function invalidateAll() { // Check for request forgeries JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); $filters = $this->input->get('filter', array(), 'array'); if (isset($filters['subject']) && $filters['subject'] != '') { $subject = $filters['subject']; } else { $this->setError(JText::_('JERROR_NO_ITEMS_SELECTED')); } // Get the model. /** @var PrivacyModelConsents $model */ $model = $this->getModel(); // Publish the items. if (!$model->invalidateAll($subject)) { $this->setError($model->getError()); } $message = JText::_('COM_PRIVACY_CONSENTS_INVALIDATED_ALL'); $this->setRedirect(JRoute::_('index.php?option=com_privacy&view=consents', false), $message); } } controllers/request.php000064400000023106152325744620011327 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Request management controller class. * * @since 3.9.0 */ class PrivacyControllerRequest extends JControllerForm { /** * Method to complete a request. * * @param string $key The name of the primary key of the URL variable. * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). * * @return boolean * * @since 3.9.0 */ public function complete($key = null, $urlVar = null) { // Check for request forgeries. JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); /** @var PrivacyModelRequest $model */ $model = $this->getModel(); /** @var PrivacyTableRequest $table */ $table = $model->getTable(); // Determine the name of the primary key for the data. if (empty($key)) { $key = $table->getKeyName(); } // To avoid data collisions the urlVar may be different from the primary key. if (empty($urlVar)) { $urlVar = $key; } $recordId = $this->input->getInt($urlVar); $item = $model->getItem($recordId); // Ensure this record can transition to the requested state if (!$this->canTransition($item, '2')) { $this->setError(\JText::_('COM_PRIVACY_ERROR_COMPLETE_TRANSITION_NOT_PERMITTED')); $this->setMessage($this->getError(), 'error'); $this->setRedirect( \JRoute::_( 'index.php?option=com_privacy&view=request&id=' . $recordId, false ) ); return false; } // Build the data array for the update $data = array( $key => $recordId, 'status' => '2', ); // Access check. if (!$this->allowSave($data, $key)) { $this->setError(\JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED')); $this->setMessage($this->getError(), 'error'); $this->setRedirect( \JRoute::_( 'index.php?option=com_privacy&view=request&id=' . $recordId, false ) ); return false; } // Attempt to save the data. if (!$model->save($data)) { // Redirect back to the edit screen. $this->setError(\JText::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError())); $this->setMessage($this->getError(), 'error'); $this->setRedirect( \JRoute::_( 'index.php?option=com_privacy&view=request&id=' . $recordId, false ) ); return false; } // Log the request completed $model->logRequestCompleted($recordId); $this->setMessage(\JText::_('COM_PRIVACY_REQUEST_COMPLETED')); $url = 'index.php?option=com_privacy&view=requests'; // Check if there is a return value $return = $this->input->get('return', null, 'base64'); if (!is_null($return) && \JUri::isInternal(base64_decode($return))) { $url = base64_decode($return); } // Redirect to the list screen. $this->setRedirect(\JRoute::_($url, false)); return true; } /** * Method to email the data export for a request. * * @return boolean * * @since 3.9.0 */ public function emailexport() { // Check for request forgeries. $this->checkToken('get'); /** @var PrivacyModelExport $model */ $model = $this->getModel('Export'); $recordId = $this->input->getUint('id'); if (!$model->emailDataExport($recordId)) { // Redirect back to the edit screen. $this->setError(\JText::sprintf('COM_PRIVACY_ERROR_EXPORT_EMAIL_FAILED', $model->getError())); $this->setMessage($this->getError(), 'error'); } else { $this->setMessage(\JText::_('COM_PRIVACY_EXPORT_EMAILED')); } $url = 'index.php?option=com_privacy&view=requests'; // Check if there is a return value $return = $this->input->get('return', null, 'base64'); if (!is_null($return) && \JUri::isInternal(base64_decode($return))) { $url = base64_decode($return); } // Redirect to the list screen. $this->setRedirect(\JRoute::_($url, false)); return true; } /** * Method to invalidate a request. * * @param string $key The name of the primary key of the URL variable. * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). * * @return boolean * * @since 3.9.0 */ public function invalidate($key = null, $urlVar = null) { // Check for request forgeries. JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); /** @var PrivacyModelRequest $model */ $model = $this->getModel(); /** @var PrivacyTableRequest $table */ $table = $model->getTable(); // Determine the name of the primary key for the data. if (empty($key)) { $key = $table->getKeyName(); } // To avoid data collisions the urlVar may be different from the primary key. if (empty($urlVar)) { $urlVar = $key; } $recordId = $this->input->getInt($urlVar); $item = $model->getItem($recordId); // Ensure this record can transition to the requested state if (!$this->canTransition($item, '-1')) { $this->setError(\JText::_('COM_PRIVACY_ERROR_INVALID_TRANSITION_NOT_PERMITTED')); $this->setMessage($this->getError(), 'error'); $this->setRedirect( \JRoute::_( 'index.php?option=com_privacy&view=request&id=' . $recordId, false ) ); return false; } // Build the data array for the update $data = array( $key => $recordId, 'status' => '-1', ); // Access check. if (!$this->allowSave($data, $key)) { $this->setError(\JText::_('JLIB_APPLICATION_ERROR_SAVE_NOT_PERMITTED')); $this->setMessage($this->getError(), 'error'); $this->setRedirect( \JRoute::_( 'index.php?option=com_privacy&view=request&id=' . $recordId, false ) ); return false; } // Attempt to save the data. if (!$model->save($data)) { // Redirect back to the edit screen. $this->setError(\JText::sprintf('JLIB_APPLICATION_ERROR_SAVE_FAILED', $model->getError())); $this->setMessage($this->getError(), 'error'); $this->setRedirect( \JRoute::_( 'index.php?option=com_privacy&view=request&id=' . $recordId, false ) ); return false; } // Log the request invalidated $model->logRequestInvalidated($recordId); $this->setMessage(\JText::_('COM_PRIVACY_REQUEST_INVALIDATED')); $url = 'index.php?option=com_privacy&view=requests'; // Check if there is a return value $return = $this->input->get('return', null, 'base64'); if (!is_null($return) && \JUri::isInternal(base64_decode($return))) { $url = base64_decode($return); } // Redirect to the list screen. $this->setRedirect(\JRoute::_($url, false)); return true; } /** * Method to remove the user data for a privacy remove request. * * @return boolean * * @since 3.9.0 */ public function remove() { // Check for request forgeries. $this->checkToken('request'); /** @var PrivacyModelRemove $model */ $model = $this->getModel('Remove'); $recordId = $this->input->getUint('id'); if (!$model->removeDataForRequest($recordId)) { // Redirect back to the edit screen. $this->setError(\JText::sprintf('COM_PRIVACY_ERROR_REMOVE_DATA_FAILED', $model->getError())); $this->setMessage($this->getError(), 'error'); $this->setRedirect( \JRoute::_( 'index.php?option=com_privacy&view=request&id=' . $recordId, false ) ); return false; } $this->setMessage(\JText::_('COM_PRIVACY_DATA_REMOVED')); $url = 'index.php?option=com_privacy&view=requests'; // Check if there is a return value $return = $this->input->get('return', null, 'base64'); if (!is_null($return) && \JUri::isInternal(base64_decode($return))) { $url = base64_decode($return); } // Redirect to the list screen. $this->setRedirect(\JRoute::_($url, false)); return true; } /** * Function that allows child controller access to model data after the data has been saved. * * @param \JModelLegacy $model The data model object. * @param array $validData The validated data. * * @return void * * @since 3.9.0 */ protected function postSaveHook(\JModelLegacy $model, $validData = array()) { // This hook only processes new items if (!$model->getState($model->getName() . '.new', false)) { return; } if (!$model->logRequestCreated($model->getState($model->getName() . '.id'))) { if ($error = $model->getError()) { JFactory::getApplication()->enqueueMessage($error, 'warning'); } } if (!$model->notifyUserAdminCreatedRequest($model->getState($model->getName() . '.id'))) { if ($error = $model->getError()) { JFactory::getApplication()->enqueueMessage($error, 'warning'); } } else { JFactory::getApplication()->enqueueMessage(JText::_('COM_PRIVACY_MSG_CONFIRM_EMAIL_SENT_TO_USER')); } } /** * Method to determine if an item can transition to the specified status. * * @param object $item The item being updated. * @param string $newStatus The new status of the item. * * @return boolean * * @since 3.9.0 */ private function canTransition($item, $newStatus) { switch ($item->status) { case '0': // A pending item can only move to invalid through this controller due to the requirement for a user to confirm the request return $newStatus === '-1'; case '1': // A confirmed item can be marked completed or invalid return in_array($newStatus, array('-1', '2'), true); // An item which is already in an invalid or complete state cannot transition, likewise if we don't know the state don't change anything case '-1': case '2': default: return false; } } } controllers/request.xml.php000064400000001122152325744620012120 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Request management controller class. * * @since 3.9.0 */ class PrivacyControllerRequest extends JControllerLegacy { /** * Method to export the data for a request. * * @return $this * * @since 3.9.0 */ public function export() { $this->input->set('view', 'export'); return $this->display(); } } controllers/requests.php000064400000001653152325744620011515 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Requests management controller class. * * @since 3.9.0 */ class PrivacyControllerRequests extends JControllerAdmin { /** * Method to get a model object, loading it if required. * * @param string $name The model name. Optional. * @param string $prefix The class prefix. Optional. * @param array $config Configuration array for model. Optional. * * @return JModelLegacy|boolean Model object on success; otherwise false on failure. * * @since 3.9.0 */ public function getModel($name = 'Request', $prefix = 'PrivacyModel', $config = array('ignore_request' => true)) { return parent::getModel($name, $prefix, $config); } } helpers/export/domain.php000064400000002421152325744620011520 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; JLoader::register('PrivacyExportItem', __DIR__ . '/item.php'); /** * Data object representing all data contained in a domain. * * A domain is typically a single database table and the items within the domain are separate rows from the table. * * @since 3.9.0 */ class PrivacyExportDomain { /** * The name of this domain * * @var string * @since 3.9.0 */ public $name; /** * A short description of the data in this domain * * @var string * @since 3.9.0 */ public $description; /** * The items belonging to this domain * * @var PrivacyExportItem[] * @since 3.9.0 */ protected $items = array(); /** * Add an item to the domain * * @param PrivacyExportItem $item The item to add * * @return void * * @since 3.9.0 */ public function addItem(PrivacyExportItem $item) { $this->items[] = $item; } /** * Get the domain's items * * @return PrivacyExportItem[] * * @since 3.9.0 */ public function getItems() { return $this->items; } } helpers/export/field.php000064400000001054152325744620011335 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Data object representing a field within an item. * * @since 3.9.0 */ class PrivacyExportField { /** * The name of this field * * @var string * @since 3.9.0 */ public $name; /** * The field's value * * @var mixed * @since 3.9.0 */ public $value; } helpers/export/item.php000064400000002237152325744620011214 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; JLoader::register('PrivacyExportField', __DIR__ . '/field.php'); /** * Data object representing a single item within a domain. * * An item is typically a single row from a database table. * * @since 3.9.0 */ class PrivacyExportItem { /** * The primary identifier of this item, typically the primary key for a database row. * * @var integer * @since 3.9.0 */ public $id; /** * The fields belonging to this item * * @var PrivacyExportField[] * @since 3.9.0 */ protected $fields = array(); /** * Add a field to the item * * @param PrivacyExportField $field The field to add * * @return void * * @since 3.9.0 */ public function addField(PrivacyExportField $field) { $this->fields[] = $field; } /** * Get the item's fields * * @return PrivacyExportField[] * * @since 3.9.0 */ public function getFields() { return $this->fields; } } helpers/html/helper.php000064400000002016152325744620011153 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Privacy component HTML helper. * * @since 3.9.0 */ class PrivacyHtmlHelper { /** * Render a status label * * @param integer $status The item status * * @return string * * @since 3.9.0 */ public static function statusLabel($status) { switch ($status) { case 2: return '<span class="label label-success">' . JText::_('COM_PRIVACY_STATUS_COMPLETED') . '</span>'; case 1: return '<span class="label label-info">' . JText::_('COM_PRIVACY_STATUS_CONFIRMED') . '</span>'; case -1: return '<span class="label label-important">' . JText::_('COM_PRIVACY_STATUS_INVALID') . '</span>'; default: case 0: return '<span class="label label-warning">' . JText::_('COM_PRIVACY_STATUS_PENDING') . '</span>'; } } } helpers/removal/status.php000064400000001474152325744620011727 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Data object communicating the status of whether the data for an information request can be removed. * * Typically, this object will only be used to communicate data will be removed. * * @since 3.9.0 */ class PrivacyRemovalStatus { /** * Flag indicating the status reported by the plugin on whether the information can be removed * * @var boolean * @since 3.9.0 */ public $canRemove = true; /** * A status message indicating the reason data can or cannot be removed * * @var string * @since 3.9.0 */ public $reason; } helpers/plugin.php000064400000007222152325744620010232 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; JLoader::register('PrivacyExportDomain', __DIR__ . '/export/domain.php'); JLoader::register('PrivacyExportField', __DIR__ . '/export/field.php'); JLoader::register('PrivacyExportItem', __DIR__ . '/export/item.php'); JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php'); /** * Base class for privacy plugins * * @since 3.9.0 */ abstract class PrivacyPlugin extends JPlugin { /** * Database object * * @var JDatabaseDriver * @since 3.9.0 */ protected $db; /** * Affects constructor behaviour. If true, language files will be loaded automatically. * * @var boolean * @since 3.9.0 */ protected $autoloadLanguage = true; /** * Create a new domain object * * @param string $name The domain's name * @param string $description The domain's description * * @return PrivacyExportDomain * * @since 3.9.0 */ protected function createDomain($name, $description = '') { $domain = new PrivacyExportDomain; $domain->name = $name; $domain->description = $description; return $domain; } /** * Create an item object for an array * * @param array $data The array data to convert * @param integer|null $itemId The ID of this item * * @return PrivacyExportItem * * @since 3.9.0 */ protected function createItemFromArray(array $data, $itemId = null) { $item = new PrivacyExportItem; $item->id = $itemId; foreach ($data as $key => $value) { if (is_object($value)) { $value = (array) $value; } if (is_array($value)) { $value = print_r($value, true); } $field = new PrivacyExportField; $field->name = $key; $field->value = $value; $item->addField($field); } return $item; } /** * Create an item object for a JTable object * * @param JTable $table The JTable object to convert * * @return PrivacyExportItem * * @since 3.9.0 */ protected function createItemForTable($table) { $data = array(); foreach (array_keys($table->getFields()) as $fieldName) { $data[$fieldName] = $table->$fieldName; } return $this->createItemFromArray($data, $table->{$table->getKeyName(false)}); } /** * Helper function to create the domain for the items custom fields. * * @param string $context The context * @param array $items The items * * @return PrivacyExportDomain * * @since 3.9.0 */ protected function createCustomFieldsDomain($context, $items = array()) { if (!is_array($items)) { $items = array($items); } $parts = FieldsHelper::extract($context); if (!$parts) { return array(); } $type = str_replace('com_', '', $parts[0]); $domain = $this->createDomain($type . '_' . $parts[1] . '_custom_fields', 'joomla_' . $type . '_' . $parts[1] . '_custom_fields_data'); foreach ($items as $item) { // Get item's fields, also preparing their value property for manual display $fields = FieldsHelper::getFields($parts[0] . '.' . $parts[1], $item); foreach ($fields as $field) { $fieldValue = is_array($field->value) ? implode(', ', $field->value) : $field->value; $data = array( $type . '_id' => $item->id, 'field_name' => $field->name, 'field_title' => $field->title, 'field_value' => $fieldValue, ); $domain->addItem($this->createItemFromArray($data)); } } return $domain; } } helpers/privacy.php000064400000005437152325744620010417 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\CMS\Factory; /** * Privacy component helper. * * @since 3.9.0 */ class PrivacyHelper extends JHelperContent { /** * Configure the Linkbar. * * @param string $vName The name of the active view. * * @return void * * @since 3.9.0 */ public static function addSubmenu($vName) { JHtmlSidebar::addEntry( JText::_('COM_PRIVACY_SUBMENU_DASHBOARD'), 'index.php?option=com_privacy&view=dashboard', $vName === 'dashboard' ); JHtmlSidebar::addEntry( JText::_('COM_PRIVACY_SUBMENU_REQUESTS'), 'index.php?option=com_privacy&view=requests', $vName === 'requests' ); JHtmlSidebar::addEntry( JText::_('COM_PRIVACY_SUBMENU_CAPABILITIES'), 'index.php?option=com_privacy&view=capabilities', $vName === 'capabilities' ); JHtmlSidebar::addEntry( JText::_('COM_PRIVACY_SUBMENU_CONSENTS'), 'index.php?option=com_privacy&view=consents', $vName === 'consents' ); } /** * Render the data request as a XML document. * * @param PrivacyExportDomain[] $exportData The data to be exported. * * @return string * * @since 3.9.0 */ public static function renderDataAsXml(array $exportData) { $export = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><data-export />'); foreach ($exportData as $domain) { $xmlDomain = $export->addChild('domain'); $xmlDomain->addAttribute('name', $domain->name); $xmlDomain->addAttribute('description', $domain->description); foreach ($domain->getItems() as $item) { $xmlItem = $xmlDomain->addChild('item'); if ($item->id) { $xmlItem->addAttribute('id', $item->id); } foreach ($item->getFields() as $field) { $xmlItem->{$field->name} = $field->value; } } } $dom = new DOMDocument; $dom->loadXML($export->asXML()); $dom->formatOutput = true; return $dom->saveXML(); } /** * Gets the privacyconsent system plugin extension id. * * @return integer The privacyconsent system plugin extension id. * * @since 3.9.2 */ public static function getPrivacyConsentPluginId() { $db = Factory::getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('extension_id')) ->from($db->quoteName('#__extensions')) ->where($db->quoteName('folder') . ' = ' . $db->quote('system')) ->where($db->quoteName('element') . ' = ' . $db->quote('privacyconsent')); $db->setQuery($query); try { $result = (int) $db->loadResult(); } catch (RuntimeException $e) { JError::raiseWarning(500, $e->getMessage()); } return $result; } } models/fields/requeststatus.php000064400000001525152325744620012757 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; JFormHelper::loadFieldClass('predefinedlist'); /** * Form Field to load a list of request statuses * * @since 3.9.0 */ class PrivacyFormFieldRequeststatus extends JFormFieldPredefinedList { /** * The form field type. * * @var string * @since 3.9.0 */ public $type = 'RequestStatus'; /** * Available statuses * * @var array * @since 3.9.0 */ protected $predefinedOptions = array( '-1' => 'COM_PRIVACY_STATUS_INVALID', '0' => 'COM_PRIVACY_STATUS_PENDING', '1' => 'COM_PRIVACY_STATUS_CONFIRMED', '2' => 'COM_PRIVACY_STATUS_COMPLETED', ); } models/fields/requesttype.php000064400000001443152325744620012414 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; JFormHelper::loadFieldClass('predefinedlist'); /** * Form Field to load a list of request types * * @since 3.9.0 */ class PrivacyFormFieldRequesttype extends JFormFieldPredefinedList { /** * The form field type. * * @var string * @since 3.9.0 */ public $type = 'RequestType'; /** * Available types * * @var array * @since 3.9.0 */ protected $predefinedOptions = array( 'export' => 'COM_PRIVACY_HEADING_REQUEST_TYPE_TYPE_EXPORT', 'remove' => 'COM_PRIVACY_HEADING_REQUEST_TYPE_TYPE_REMOVE', ); } models/forms/filter_consents.xml000064400000004423152325744620013115 0ustar00<?xml version="1.0" encoding="utf-8"?> <form> <fieldset addfieldpath="/administrator/components/com_privacy/models/fields" /> <fields name="filter"> <field name="search" type="text" inputmode="search" label="COM_PRIVACY_FILTER_SEARCH_LABEL" description="COM_PRIVACY_SEARCH_IN_USERNAME" hint="JSEARCH_FILTER" /> <field name="state" type="list" label="COM_PRIVACY_CONSENTS_FILTER_STATE" onchange="this.form.submit();" > <option value="">JOPTION_SELECT_PUBLISHED</option> <option value="1">COM_PRIVACY_CONSENTS_STATE_VALID</option> <option value="0">COM_PRIVACY_CONSENTS_STATE_OBSOLETE</option> <option value="-1">COM_PRIVACY_CONSENTS_STATE_INVALIDATED</option> </field> <field name="subject" type="sql" label="COM_PRIVACY_CONSENTS_FILTER_SUBJECT" sql_select="subject" sql_from="#__privacy_consents" sql_group="subject" sql_order="subject ASC" key_field="subject" translate="true" onchange="this.form.submit();" > <option value="">COM_PRIVACY_CONSENTS_SUBJECT_DEFAULT</option> </field> </fields> <fields name="list"> <field name="fullordering" type="list" label="JGLOBAL_SORT_BY" description="JGLOBAL_SORT_BY" onchange="this.form.submit();" default="a.id DESC" validate="options" > <option value="a.state ASC">COM_PRIVACY_HEADING_STATUS_ASC</option> <option value="a.state DESC">COM_PRIVACY_HEADING_STATUS_DESC</option> <option value="u.username ASC">COM_PRIVACY_HEADING_USERNAME_ASC</option> <option value="u.username DESC">COM_PRIVACY_HEADING_USERNAME_DESC</option> <option value="a.user_id ASC">COM_PRIVACY_HEADING_USERID_ASC</option> <option value="a.user_id DESC">COM_PRIVACY_HEADING_USERID_DESC</option> <option value="a.subject ASC">COM_PRIVACY_HEADING_SUBJECT_ASC</option> <option value="a.subject DESC">COM_PRIVACY_HEADING_SUBJECT_DESC</option> <option value="a.created ASC">COM_PRIVACY_HEADING_CREATED_ASC</option> <option value="a.created DESC">COM_PRIVACY_HEADING_CREATED_DESC</option> <option value="a.id ASC">JGRID_HEADING_ID_ASC</option> <option value="a.id DESC">JGRID_HEADING_ID_DESC</option> </field> <field name="limit" type="limitbox" class="input-mini" default="25" onchange="this.form.submit();" /> </fields> </form> models/forms/filter_requests.xml000064400000003522152325744620013133 0ustar00<?xml version="1.0" encoding="utf-8"?> <form> <fieldset addfieldpath="/administrator/components/com_privacy/models/fields" /> <fields name="filter"> <field name="search" type="text" inputmode="search" label="COM_PRIVACY_FILTER_SEARCH_LABEL" description="COM_PRIVACY_SEARCH_IN_EMAIL" hint="JSEARCH_FILTER" /> <field name="status" type="privacy.requeststatus" label="COM_PRIVACY_FILTER_STATUS" description="COM_PRIVACY_FILTER_STATUS_DESC" onchange="this.form.submit();" > <option value="">JOPTION_SELECT_PUBLISHED</option> </field> <field name="request_type" type="privacy.requesttype" label="COM_PRIVACY_FILTER_REQUEST_TYPE" description="COM_PRIVACY_FILTER_REQUEST_TYPE_DESC" onchange="this.form.submit();" > <option value="">COM_PRIVACY_SELECT_REQUEST_TYPE</option> </field> </fields> <fields name="list"> <field name="fullordering" type="list" label="JGLOBAL_SORT_BY" description="JGLOBAL_SORT_BY" onchange="this.form.submit();" default="a.id DESC" validate="options" > <option value="">JGLOBAL_SORT_BY</option> <option value="a.email ASC">COM_PRIVACY_HEADING_EMAIL_ASC</option> <option value="a.email DESC">COM_PRIVACY_HEADING_EMAIL_DESC</option> <option value="a.request_type ASC">COM_PRIVACY_HEADING_REQUEST_TYPE_ASC</option> <option value="a.request_type DESC">COM_PRIVACY_HEADING_REQUEST_TYPE_DESC</option> <option value="a.requested_at ASC">COM_PRIVACY_HEADING_REQUESTED_AT_ASC</option> <option value="a.requested_at DESC">COM_PRIVACY_HEADING_REQUESTED_AT_DESC</option> <option value="a.id ASC">JGRID_HEADING_ID_ASC</option> <option value="a.id DESC">JGRID_HEADING_ID_DESC</option> </field> <field name="limit" type="limitbox" class="input-mini" default="25" onchange="this.form.submit();" /> </fields> </form> models/forms/request.xml000064400000002434152325744620011404 0ustar00<?xml version="1.0" encoding="utf-8"?> <form> <fieldset addfieldpath="/administrator/components/com_privacy/models/fields"> <field name="email" type="email" label="JGLOBAL_EMAIL" description="COM_PRIVACY_USER_FIELD_EMAIL_DESC" required="true" size="30" validate="email" /> <field name="status" type="list" label="JSTATUS" description="COM_PRIVACY_FIELD_STATUS_DESC" filter="int" default="0" validate="options" readonly="true" > <option value="0">COM_PRIVACY_STATUS_PENDING</option> <option value="-1">COM_PRIVACY_STATUS_INVALID</option> <option value="1">COM_PRIVACY_STATUS_CONFIRMED</option> <option value="2">COM_PRIVACY_STATUS_COMPLETED</option> </field> <field name="request_type" type="list" label="COM_PRIVACY_FIELD_REQUEST_TYPE_LABEL" description="COM_PRIVACY_FIELD_REQUEST_TYPE_DESC" filter="string" default="export" validate="options" > <option value="export">COM_PRIVACY_HEADING_REQUEST_TYPE_TYPE_EXPORT</option> <option value="remove">COM_PRIVACY_HEADING_REQUEST_TYPE_TYPE_REMOVE</option> </field> <field name="id" type="number" label="JGLOBAL_FIELD_ID_LABEL" description="JGLOBAL_FIELD_ID_DESC" class="readonly" default="0" readonly="true" /> </fieldset> </form> models/capabilities.php000064400000006520152325744620011206 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Capabilities model class. * * @since 3.9.0 */ class PrivacyModelCapabilities extends JModelLegacy { /** * Retrieve the extension capabilities. * * @return array * * @since 3.9.0 */ public function getCapabilities() { $app = JFactory::getApplication(); /* * Capabilities will be collected in two parts: * * 1) Core capabilities - This will cover the core API, i.e. all library level classes * 2) Extension capabilities - This will be collected by a plugin hook to select plugin groups * * Plugins which report capabilities should return an associative array with a single root level key which is used as the title * for the reporting section and an array with each value being a separate capability. All capability messages should be translated * by the extension when building the array. An example of the structure expected to be returned from plugins can be found in the * $coreCapabilities array below. */ $coreCapabilities = array( JText::_('COM_PRIVACY_HEADING_CORE_CAPABILITIES') => array( JText::_('COM_PRIVACY_CORE_CAPABILITY_SESSION_IP_ADDRESS_AND_COOKIE'), JText::sprintf('COM_PRIVACY_CORE_CAPABILITY_LOGGING_IP_ADDRESS', $app->get('log_path', JPATH_ADMINISTRATOR . '/logs')), JText::_('COM_PRIVACY_CORE_CAPABILITY_COMMUNICATION_WITH_JOOMLA_ORG'), ) ); /* * We will search for capabilities from the following plugin groups: * * - Authentication: These plugins by design process user information and may have capabilities such as creating cookies * - Captcha: These plugins may communicate information to third party systems * - Installer: These plugins can add additional install capabilities to the Extension Manager, such as the Install from Web service * - Privacy: These plugins are the primary integration point into this component * - User: These plugins are intended to extend the user management system * * This is in addition to plugin groups which are imported before this method is triggered, generally this is the system group. */ JPluginHelper::importPlugin('authentication'); JPluginHelper::importPlugin('captcha'); JPluginHelper::importPlugin('installer'); JPluginHelper::importPlugin('privacy'); JPluginHelper::importPlugin('user'); $pluginResults = $app->triggerEvent('onPrivacyCollectAdminCapabilities'); // We are going to "cheat" here and include this component's capabilities without using a plugin $extensionCapabilities = array( JText::_('COM_PRIVACY') => array( JText::_('COM_PRIVACY_EXTENSION_CAPABILITY_PERSONAL_INFO'), ) ); foreach ($pluginResults as $pluginResult) { $extensionCapabilities += $pluginResult; } // Sort the extension list alphabetically ksort($extensionCapabilities); // Always prepend the core capabilities to the array return $coreCapabilities + $extensionCapabilities; } /** * Method to auto-populate the model state. * * @return void * * @since 3.9.0 */ protected function populateState() { // Load the parameters. $this->setState('params', JComponentHelper::getParams('com_privacy')); } } models/consents.php000064400000012415152325744620010411 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\Utilities\ArrayHelper; /** * Consents management model class. * * @since 3.9.0 */ class PrivacyModelConsents extends JModelList { /** * Constructor. * * @param array $config An optional associative array of configuration settings. * * @since 3.9.0 */ public function __construct($config = array()) { if (empty($config['filter_fields'])) { $config['filter_fields'] = array( 'id', 'a.id', 'user_id', 'a.user_id', 'subject', 'a.subject', 'created', 'a.created', 'username', 'u.username', 'state', 'a.state' ); } parent::__construct($config); } /** * Method to get a JDatabaseQuery object for retrieving the data set from a database. * * @return JDatabaseQuery * * @since 3.9.0 */ protected function getListQuery() { // Create a new query object. $db = $this->getDbo(); $query = $db->getQuery(true); // Select the required fields from the table. $query->select($this->getState('list.select', 'a.*')); $query->from($db->quoteName('#__privacy_consents', 'a')); // Join over the users for the username. $query->select($db->quoteName('u.username', 'username')); $query->join('LEFT', $db->quoteName('#__users', 'u') . ' ON u.id = a.user_id'); // Filter by search in email $search = $this->getState('filter.search'); if (!empty($search)) { if (stripos($search, 'id:') === 0) { $query->where($db->quoteName('a.id') . ' = ' . (int) substr($search, 3)); } elseif (stripos($search, 'uid:') === 0) { $query->where($db->quoteName('a.user_id') . ' = ' . (int) substr($search, 4)); } else { $search = $db->quote('%' . $db->escape($search, true) . '%'); $query->where('(' . $db->quoteName('u.username') . ' LIKE ' . $search . ')'); } } $state = $this->getState('filter.state'); if ($state != '') { $query->where($db->quoteName('a.state') . ' = ' . (int) $state); } // Handle the list ordering. $ordering = $this->getState('list.ordering'); $direction = $this->getState('list.direction'); if (!empty($ordering)) { $query->order($db->escape($ordering) . ' ' . $db->escape($direction)); } return $query; } /** * 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 * * @since 3.9.0 */ protected function getStoreId($id = '') { // Compile the store id. $id .= ':' . $this->getState('filter.search'); return parent::getStoreId($id); } /** * Method to auto-populate the model state. * * Note. Calling getState in this method will result in recursion. * * @param string $ordering An optional ordering field. * @param string $direction An optional direction (asc|desc). * * @return void * * @since 3.9.0 */ protected function populateState($ordering = 'a.id', $direction = 'desc') { // Load the filter state. $this->setState( 'filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search') ); $this->setState( 'filter.subject', $this->getUserStateFromRequest($this->context . '.filter.subject', 'filter_subject') ); $this->setState( 'filter.state', $this->getUserStateFromRequest($this->context . '.filter.state', 'filter_state') ); // Load the parameters. $this->setState('params', JComponentHelper::getParams('com_privacy')); // List state information. parent::populateState($ordering, $direction); } /** * Method to invalidate specific consents. * * @param array $pks The ids of the consents to invalidate. * * @return boolean True on success. */ public function invalidate($pks) { // Sanitize the ids. $pks = (array) $pks; $pks = ArrayHelper::toInteger($pks); try { $db = $this->getDbo(); $query = $db->getQuery(true) ->update($db->quoteName('#__privacy_consents')) ->set($db->quoteName('state') . ' = -1') ->where($db->quoteName('id') . ' IN (' . implode(',', $pks) . ')') ->where($db->quoteName('state') . ' = 1'); $db->setQuery($query); $db->execute(); } catch (JDatabaseExceptionExecuting $e) { $this->setError($e->getMessage()); return false; } return true; } /** * Method to invalidate a group of specific consents. * * @param array $subject The subject of the consents to invalidate. * * @return boolean True on success. */ public function invalidateAll($subject) { try { $db = $this->getDbo(); $query = $db->getQuery(true) ->update($db->quoteName('#__privacy_consents')) ->set($db->quoteName('state') . ' = -1') ->where($db->quoteName('subject') . ' = ' . $db->quote($subject)) ->where($db->quoteName('state') . ' = 1'); $db->setQuery($query); $db->execute(); } catch (JDatabaseExceptionExecuting $e) { $this->setError($e->getMessage()); return false; } return true; } } models/dashboard.php000064400000010100152325744620010471 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\CMS\Router\Route; /** * Dashboard model class. * * @since 3.9.0 */ class PrivacyModelDashboard extends JModelLegacy { /** * Get the information about the published privacy policy * * @return array Array containing a status of whether a privacy policy is set and a link to the policy document for editing * * @since 3.9.0 */ public function getPrivacyPolicyInfo() { $policy = array( 'published' => false, 'articlePublished' => false, 'editLink' => '', ); /* * Prior to 3.9.0 it was common for a plugin such as the User - Profile plugin to define a privacy policy or * terms of service article, therefore we will also import the user plugin group to process this event. */ JPluginHelper::importPlugin('privacy'); JPluginHelper::importPlugin('user'); JFactory::getApplication()->triggerEvent('onPrivacyCheckPrivacyPolicyPublished', array(&$policy)); return $policy; } /** * Get a count of the active information requests grouped by type and status * * @return array Array containing site privacy requests * * @since 3.9.0 */ public function getRequestCounts() { $db = $this->getDbo(); $query = $db->getQuery(true) ->select( array( 'COUNT(*) AS count', $db->quoteName('status'), $db->quoteName('request_type'), ) ) ->from($db->quoteName('#__privacy_requests')) ->group($db->quoteName('status')) ->group($db->quoteName('request_type')); $db->setQuery($query); return $db->loadObjectList(); } /** * Check whether there is a menu item for the request form * * @return array Array containing a status of whether a menu is published for the request form and its current link * * @since 3.9.0 */ public function getRequestFormPublished() { $status = array( 'exists' => false, 'published' => false, 'link' => '', ); $db = $this->getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('id') . ', ' . $db->quoteName('published') . ', ' . $db->quoteName('language')) ->from($db->quoteName('#__menu')) ->where($db->quoteName('client_id') . ' = 0') ->where($db->quoteName('link') . ' = ' . $db->quote('index.php?option=com_privacy&view=request')); $db->setQuery($query); $menuItem = $db->loadObject(); // Check if the menu item exists in database if ($menuItem) { $status['exists'] = true; // Check if the menu item is published if ($menuItem->published == 1) { $status['published'] = true; } // Add language to the url if the site is multilingual if (JLanguageMultilang::isEnabled() && $menuItem->language && $menuItem->language !== '*') { $lang = '&lang=' . $menuItem->language; } else { $lang = ''; } } $linkMode = JFactory::getApplication()->get('force_ssl', 0) == 2 ? Route::TLS_FORCE : Route::TLS_IGNORE; if (!$menuItem) { if (JLanguageMultilang::isEnabled()) { // Find the Itemid of the home menu item tagged to the site default language $params = JComponentHelper::getParams('com_languages'); $defaultSiteLanguage = $params->get('site'); $db = $this->getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('id')) ->from($db->quoteName('#__menu')) ->where($db->quoteName('client_id') . ' = 0') ->where($db->quoteName('home') . ' = 1') ->where($db->quoteName('language') . ' = ' . $db->quote($defaultSiteLanguage)); $db->setQuery($query); $homeId = (int) $db->loadResult(); $itemId = $homeId ? '&Itemid=' . $homeId : ''; } else { $itemId = ''; } $status['link'] = JRoute::link('site', 'index.php?option=com_privacy&view=request' . $itemId, true, $linkMode); } else { $status['link'] = JRoute::link('site', 'index.php?Itemid=' . $menuItem->id . $lang, true, $linkMode); } return $status; } } models/export.php000064400000021266152325744620010102 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; JLoader::register('PrivacyHelper', JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/privacy.php'); /** * Export model class. * * @since 3.9.0 */ class PrivacyModelExport extends JModelLegacy { /** * Create the export document for an information request. * * @param integer $id The request ID to process * * @return PrivacyExportDomain[]|boolean A SimpleXMLElement object for a successful export or boolean false on an error * * @since 3.9.0 */ public function collectDataForExportRequest($id = null) { $id = !empty($id) ? $id : (int) $this->getState($this->getName() . '.request_id'); if (!$id) { $this->setError(JText::_('COM_PRIVACY_ERROR_REQUEST_ID_REQUIRED_FOR_EXPORT')); return false; } /** @var PrivacyTableRequest $table */ $table = $this->getTable(); if (!$table->load($id)) { $this->setError($table->getError()); return false; } if ($table->request_type !== 'export') { $this->setError(JText::_('COM_PRIVACY_ERROR_REQUEST_TYPE_NOT_EXPORT')); return false; } if ($table->status != 1) { $this->setError(JText::_('COM_PRIVACY_ERROR_CANNOT_EXPORT_UNCONFIRMED_REQUEST')); return false; } // If there is a user account associated with the email address, load it here for use in the plugins $db = $this->getDbo(); $userId = (int) $db->setQuery( $db->getQuery(true) ->select('id') ->from($db->quoteName('#__users')) ->where('LOWER(' . $db->quoteName('email') . ') = LOWER(' . $db->quote($table->email) . ')'), 0, 1 )->loadResult(); $user = $userId ? JUser::getInstance($userId) : null; // Log the export $this->logExport($table); JPluginHelper::importPlugin('privacy'); $pluginResults = JFactory::getApplication()->triggerEvent('onPrivacyExportRequest', array($table, $user)); $domains = array(); foreach ($pluginResults as $pluginDomains) { $domains = array_merge($domains, $pluginDomains); } return $domains; } /** * Email the data export to the user. * * @param integer $id The request ID to process * * @return boolean * * @since 3.9.0 */ public function emailDataExport($id = null) { $id = !empty($id) ? $id : (int) $this->getState($this->getName() . '.request_id'); if (!$id) { $this->setError(JText::_('COM_PRIVACY_ERROR_REQUEST_ID_REQUIRED_FOR_EXPORT')); return false; } $exportData = $this->collectDataForExportRequest($id); if ($exportData === false) { // Error is already set, we just need to bail return false; } /** @var PrivacyTableRequest $table */ $table = $this->getTable(); if (!$table->load($id)) { $this->setError($table->getError()); return false; } if ($table->request_type !== 'export') { $this->setError(JText::_('COM_PRIVACY_ERROR_REQUEST_TYPE_NOT_EXPORT')); return false; } if ($table->status != 1) { $this->setError(JText::_('COM_PRIVACY_ERROR_CANNOT_EXPORT_UNCONFIRMED_REQUEST')); return false; } // Log the email $this->logExportEmailed($table); /* * If there is an associated user account, we will attempt to send this email in the user's preferred language. * Because of this, it is expected that Language::_() is directly called and that the Text class is NOT used * for translating all messages. * * Error messages will still be displayed to the administrator, so those messages should continue to use the Text class. */ $lang = JFactory::getLanguage(); $db = $this->getDbo(); $userId = (int) $db->setQuery( $db->getQuery(true) ->select('id') ->from($db->quoteName('#__users')) ->where('LOWER(' . $db->quoteName('email') . ') = LOWER(' . $db->quote($table->email) . ')'), 0, 1 )->loadResult(); if ($userId) { $receiver = JUser::getInstance($userId); /* * We don't know if the user has admin access, so we will check if they have an admin language in their parameters, * falling back to the site language, falling back to the currently active language */ $langCode = $receiver->getParam('admin_language', ''); if (!$langCode) { $langCode = $receiver->getParam('language', $lang->getTag()); } $lang = JLanguage::getInstance($langCode, $lang->getDebug()); } // Ensure the right language files have been loaded $lang->load('com_privacy', JPATH_ADMINISTRATOR, null, false, true) || $lang->load('com_privacy', JPATH_ADMINISTRATOR . '/components/com_privacy', null, false, true); // The mailer can be set to either throw Exceptions or return boolean false, account for both try { $app = JFactory::getApplication(); $substitutions = array( '[SITENAME]' => $app->get('sitename'), '[URL]' => JUri::root(), '\\n' => "\n", ); $emailSubject = $lang->_('COM_PRIVACY_EMAIL_DATA_EXPORT_COMPLETED_SUBJECT'); $emailBody = $lang->_('COM_PRIVACY_EMAIL_DATA_EXPORT_COMPLETED_BODY'); foreach ($substitutions as $k => $v) { $emailSubject = str_replace($k, $v, $emailSubject); $emailBody = str_replace($k, $v, $emailBody); } $mailer = JFactory::getMailer(); $mailer->setSubject($emailSubject); $mailer->setBody($emailBody); $mailer->addRecipient($table->email); $mailer->addStringAttachment( PrivacyHelper::renderDataAsXml($exportData), 'user-data_' . JUri::getInstance()->toString(array('host')) . '.xml' ); $mailResult = $mailer->Send(); if ($mailResult instanceof JException) { // JError was already called so we just need to return now return false; } elseif ($mailResult === false) { $this->setError($mailer->ErrorInfo); return false; } return true; } catch (phpmailerException $exception) { $this->setError($exception->getMessage()); return false; } return true; } /** * Method to get a table object, load it if necessary. * * @param string $name The table name. Optional. * @param string $prefix The class prefix. Optional. * @param array $options Configuration array for model. Optional. * * @return JTable A JTable object * * @since 3.9.0 * @throws \Exception */ public function getTable($name = 'Request', $prefix = 'PrivacyTable', $options = array()) { return parent::getTable($name, $prefix, $options); } /** * Log the data export to the action log system. * * @param PrivacyTableRequest $request The request record being processed * * @return void * * @since 3.9.0 */ public function logExport(PrivacyTableRequest $request) { JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_actionlogs/models', 'ActionlogsModel'); $user = JFactory::getUser(); $message = array( 'action' => 'export', 'id' => $request->id, 'itemlink' => 'index.php?option=com_privacy&view=request&id=' . $request->id, 'userid' => $user->id, 'username' => $user->username, 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id, ); /** @var ActionlogsModelActionlog $model */ $model = JModelLegacy::getInstance('Actionlog', 'ActionlogsModel'); $model->addLog(array($message), 'COM_PRIVACY_ACTION_LOG_EXPORT', 'com_privacy.request', $user->id); } /** * Log the data export email to the action log system. * * @param PrivacyTableRequest $request The request record being processed * * @return void * * @since 3.9.0 */ public function logExportEmailed(PrivacyTableRequest $request) { JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_actionlogs/models', 'ActionlogsModel'); $user = JFactory::getUser(); $message = array( 'action' => 'export_emailed', 'id' => $request->id, 'itemlink' => 'index.php?option=com_privacy&view=request&id=' . $request->id, 'userid' => $user->id, 'username' => $user->username, 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id, ); /** @var ActionlogsModelActionlog $model */ $model = JModelLegacy::getInstance('Actionlog', 'ActionlogsModel'); $model->addLog(array($message), 'COM_PRIVACY_ACTION_LOG_EXPORT_EMAILED', 'com_privacy.request', $user->id); } /** * Method to auto-populate the model state. * * @return void * * @since 3.9.0 */ protected function populateState() { // Get the pk of the record from the request. $this->setState($this->getName() . '.request_id', JFactory::getApplication()->input->getUint('id')); // Load the parameters. $this->setState('params', JComponentHelper::getParams('com_privacy')); } } models/remove.php000064400000012615152325744620010054 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; JLoader::register('PrivacyHelper', JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/privacy.php'); JLoader::register('PrivacyRemovalStatus', JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/removal/status.php'); /** * Remove model class. * * @since 3.9.0 */ class PrivacyModelRemove extends JModelLegacy { /** * Remove the user data. * * @param integer $id The request ID to process * * @return boolean * * @since 3.9.0 */ public function removeDataForRequest($id = null) { $id = !empty($id) ? $id : (int) $this->getState($this->getName() . '.request_id'); if (!$id) { $this->setError(JText::_('COM_PRIVACY_ERROR_REQUEST_ID_REQUIRED_FOR_REMOVE')); return false; } /** @var PrivacyTableRequest $table */ $table = $this->getTable(); if (!$table->load($id)) { $this->setError($table->getError()); return false; } if ($table->request_type !== 'remove') { $this->setError(JText::_('COM_PRIVACY_ERROR_REQUEST_TYPE_NOT_REMOVE')); return false; } if ($table->status != 1) { $this->setError(JText::_('COM_PRIVACY_ERROR_CANNOT_REMOVE_UNCONFIRMED_REQUEST')); return false; } // If there is a user account associated with the email address, load it here for use in the plugins $db = $this->getDbo(); $userId = (int) $db->setQuery( $db->getQuery(true) ->select('id') ->from($db->quoteName('#__users')) ->where('LOWER(' . $db->quoteName('email') . ') = LOWER(' . $db->quote($table->email) . ')'), 0, 1 )->loadResult(); $user = $userId ? JUser::getInstance($userId) : null; $canRemove = true; JPluginHelper::importPlugin('privacy'); /** @var PrivacyRemovalStatus[] $pluginResults */ $pluginResults = JFactory::getApplication()->triggerEvent('onPrivacyCanRemoveData', array($table, $user)); foreach ($pluginResults as $status) { if (!$status->canRemove) { $this->setError($status->reason ?: JText::_('COM_PRIVACY_ERROR_CANNOT_REMOVE_DATA')); $canRemove = false; } } if (!$canRemove) { $this->logRemoveBlocked($table, $this->getErrors()); return false; } // Log the removal $this->logRemove($table); JFactory::getApplication()->triggerEvent('onPrivacyRemoveData', array($table, $user)); return true; } /** * Method to get a table object, load it if necessary. * * @param string $name The table name. Optional. * @param string $prefix The class prefix. Optional. * @param array $options Configuration array for model. Optional. * * @return JTable A JTable object * * @since 3.9.0 * @throws \Exception */ public function getTable($name = 'Request', $prefix = 'PrivacyTable', $options = array()) { return parent::getTable($name, $prefix, $options); } /** * Log the data removal to the action log system. * * @param PrivacyTableRequest $request The request record being processed * * @return void * * @since 3.9.0 */ public function logRemove(PrivacyTableRequest $request) { JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_actionlogs/models', 'ActionlogsModel'); $user = JFactory::getUser(); $message = array( 'action' => 'remove', 'id' => $request->id, 'itemlink' => 'index.php?option=com_privacy&view=request&id=' . $request->id, 'userid' => $user->id, 'username' => $user->username, 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id, ); /** @var ActionlogsModelActionlog $model */ $model = JModelLegacy::getInstance('Actionlog', 'ActionlogsModel'); $model->addLog(array($message), 'COM_PRIVACY_ACTION_LOG_REMOVE', 'com_privacy.request', $user->id); } /** * Log the data removal being blocked to the action log system. * * @param PrivacyTableRequest $request The request record being processed * @param string[] $reasons The reasons given why the record could not be removed. * * @return void * * @since 3.9.0 */ public function logRemoveBlocked(PrivacyTableRequest $request, array $reasons) { JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_actionlogs/models', 'ActionlogsModel'); $user = JFactory::getUser(); $message = array( 'action' => 'remove-blocked', 'id' => $request->id, 'itemlink' => 'index.php?option=com_privacy&view=request&id=' . $request->id, 'userid' => $user->id, 'username' => $user->username, 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id, 'reasons' => implode('; ', $reasons), ); /** @var ActionlogsModelActionlog $model */ $model = JModelLegacy::getInstance('Actionlog', 'ActionlogsModel'); $model->addLog(array($message), 'COM_PRIVACY_ACTION_LOG_REMOVE_BLOCKED', 'com_privacy.request', $user->id); } /** * Method to auto-populate the model state. * * @return void * * @since 3.9.0 */ protected function populateState() { // Get the pk of the record from the request. $this->setState($this->getName() . '.request_id', JFactory::getApplication()->input->getUint('id')); // Load the parameters. $this->setState('params', JComponentHelper::getParams('com_privacy')); } } models/request.php000064400000030073152325744620010245 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\CMS\Router\Route; /** * Request item model class. * * @since 3.9.0 */ class PrivacyModelRequest extends JModelAdmin { /** * Clean the cache * * @param string $group The cache group * @param integer $clientId The ID of the client * * @return void * * @since 3.9.0 */ protected function cleanCache($group = 'com_privacy', $clientId = 1) { parent::cleanCache('com_privacy', 1); } /** * Method for getting the form from the model. * * @param array $data Data for the form. * @param boolean $loadData True if the form is to load its own data (default case), false if not. * * @return JForm|boolean A JForm object on success, false on failure * * @since 3.9.0 */ public function getForm($data = array(), $loadData = true) { // Get the form. $form = $this->loadForm('com_privacy.request', 'request', array('control' => 'jform', 'load_data' => $loadData)); if (empty($form)) { return false; } return $form; } /** * Method to get a table object, load it if necessary. * * @param string $name The table name. Optional. * @param string $prefix The class prefix. Optional. * @param array $options Configuration array for model. Optional. * * @return JTable A JTable object * * @since 3.9.0 * @throws \Exception */ public function getTable($name = 'Request', $prefix = 'PrivacyTable', $options = array()) { return parent::getTable($name, $prefix, $options); } /** * Method to get the data that should be injected in the form. * * @return array The default data is an empty array. * * @since 3.9.0 */ protected function loadFormData() { // Check the session for previously entered form data. $data = JFactory::getApplication()->getUserState('com_privacy.edit.request.data', array()); if (empty($data)) { $data = $this->getItem(); } return $data; } /** * Log the completion of a request to the action log system. * * @param integer $id The ID of the request to process. * * @return boolean * * @since 3.9.0 */ public function logRequestCompleted($id) { /** @var PrivacyTableRequest $table */ $table = $this->getTable(); if (!$table->load($id)) { $this->setError($table->getError()); return false; } JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_actionlogs/models', 'ActionlogsModel'); $user = JFactory::getUser(); $message = array( 'action' => 'request-completed', 'requesttype' => $table->request_type, 'subjectemail' => $table->email, 'id' => $table->id, 'itemlink' => 'index.php?option=com_privacy&view=request&id=' . $table->id, 'userid' => $user->id, 'username' => $user->username, 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id, ); /** @var ActionlogsModelActionlog $model */ $model = JModelLegacy::getInstance('Actionlog', 'ActionlogsModel'); $model->addLog(array($message), 'COM_PRIVACY_ACTION_LOG_ADMIN_COMPLETED_REQUEST', 'com_privacy.request', $user->id); return true; } /** * Log the creation of a request to the action log system. * * @param integer $id The ID of the request to process. * * @return boolean * * @since 3.9.0 */ public function logRequestCreated($id) { /** @var PrivacyTableRequest $table */ $table = $this->getTable(); if (!$table->load($id)) { $this->setError($table->getError()); return false; } JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_actionlogs/models', 'ActionlogsModel'); $user = JFactory::getUser(); $message = array( 'action' => 'request-created', 'requesttype' => $table->request_type, 'subjectemail' => $table->email, 'id' => $table->id, 'itemlink' => 'index.php?option=com_privacy&view=request&id=' . $table->id, 'userid' => $user->id, 'username' => $user->username, 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id, ); /** @var ActionlogsModelActionlog $model */ $model = JModelLegacy::getInstance('Actionlog', 'ActionlogsModel'); $model->addLog(array($message), 'COM_PRIVACY_ACTION_LOG_ADMIN_CREATED_REQUEST', 'com_privacy.request', $user->id); return true; } /** * Log the invalidation of a request to the action log system. * * @param integer $id The ID of the request to process. * * @return boolean * * @since 3.9.0 */ public function logRequestInvalidated($id) { /** @var PrivacyTableRequest $table */ $table = $this->getTable(); if (!$table->load($id)) { $this->setError($table->getError()); return false; } JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_actionlogs/models', 'ActionlogsModel'); $user = JFactory::getUser(); $message = array( 'action' => 'request-invalidated', 'requesttype' => $table->request_type, 'subjectemail' => $table->email, 'id' => $table->id, 'itemlink' => 'index.php?option=com_privacy&view=request&id=' . $table->id, 'userid' => $user->id, 'username' => $user->username, 'accountlink' => 'index.php?option=com_users&task=user.edit&id=' . $user->id, ); /** @var ActionlogsModelActionlog $model */ $model = JModelLegacy::getInstance('Actionlog', 'ActionlogsModel'); $model->addLog(array($message), 'COM_PRIVACY_ACTION_LOG_ADMIN_INVALIDATED_REQUEST', 'com_privacy.request', $user->id); return true; } /** * Notifies the user that an information request has been created by a site administrator. * * Because confirmation tokens are stored in the database as a hashed value, this method will generate a new confirmation token * for the request. * * @param integer $id The ID of the request to process. * * @return boolean * * @since 3.9.0 */ public function notifyUserAdminCreatedRequest($id) { /** @var PrivacyTableRequest $table */ $table = $this->getTable(); if (!$table->load($id)) { $this->setError($table->getError()); return false; } /* * If there is an associated user account, we will attempt to send this email in the user's preferred language. * Because of this, it is expected that Language::_() is directly called and that the Text class is NOT used * for translating all messages. * * Error messages will still be displayed to the administrator, so those messages should continue to use the Text class. */ $lang = JFactory::getLanguage(); $db = $this->getDbo(); $userId = (int) $db->setQuery( $db->getQuery(true) ->select('id') ->from($db->quoteName('#__users')) ->where('LOWER(' . $db->quoteName('email') . ') = LOWER(' . $db->quote($table->email) . ')'), 0, 1 )->loadResult(); if ($userId) { $receiver = JUser::getInstance($userId); /* * We don't know if the user has admin access, so we will check if they have an admin language in their parameters, * falling back to the site language, falling back to the currently active language */ $langCode = $receiver->getParam('admin_language', ''); if (!$langCode) { $langCode = $receiver->getParam('language', $lang->getTag()); } $lang = JLanguage::getInstance($langCode, $lang->getDebug()); } // Ensure the right language files have been loaded $lang->load('com_privacy', JPATH_ADMINISTRATOR, null, false, true) || $lang->load('com_privacy', JPATH_ADMINISTRATOR . '/components/com_privacy', null, false, true); // Regenerate the confirmation token $token = JApplicationHelper::getHash(JUserHelper::genRandomPassword()); $hashedToken = JUserHelper::hashPassword($token); $table->confirm_token = $hashedToken; $table->confirm_token_created_at = JFactory::getDate()->toSql(); try { $table->store(); } catch (JDatabaseException $exception) { $this->setError($exception->getMessage()); return false; } // The mailer can be set to either throw Exceptions or return boolean false, account for both try { $app = JFactory::getApplication(); $linkMode = $app->get('force_ssl', 0) == 2 ? Route::TLS_FORCE : Route::TLS_IGNORE; $substitutions = array( '[SITENAME]' => $app->get('sitename'), '[URL]' => JUri::root(), '[TOKENURL]' => JRoute::link('site', 'index.php?option=com_privacy&view=confirm&confirm_token=' . $token, false, $linkMode, true), '[FORMURL]' => JRoute::link('site', 'index.php?option=com_privacy&view=confirm', false, $linkMode, true), '[TOKEN]' => $token, '\\n' => "\n", ); switch ($table->request_type) { case 'export': $emailSubject = $lang->_('COM_PRIVACY_EMAIL_ADMIN_REQUEST_SUBJECT_EXPORT_REQUEST'); $emailBody = $lang->_('COM_PRIVACY_EMAIL_ADMIN_REQUEST_BODY_EXPORT_REQUEST'); break; case 'remove': $emailSubject = $lang->_('COM_PRIVACY_EMAIL_ADMIN_REQUEST_SUBJECT_REMOVE_REQUEST'); $emailBody = $lang->_('COM_PRIVACY_EMAIL_ADMIN_REQUEST_BODY_REMOVE_REQUEST'); break; default: $this->setError(JText::_('COM_PRIVACY_ERROR_UNKNOWN_REQUEST_TYPE')); return false; } foreach ($substitutions as $k => $v) { $emailSubject = str_replace($k, $v, $emailSubject); $emailBody = str_replace($k, $v, $emailBody); } $mailer = JFactory::getMailer(); $mailer->setSubject($emailSubject); $mailer->setBody($emailBody); $mailer->addRecipient($table->email); $mailResult = $mailer->Send(); if ($mailResult instanceof JException) { // JError was already called so we just need to return now return false; } elseif ($mailResult === false) { $this->setError($mailer->ErrorInfo); return false; } return true; } catch (phpmailerException $exception) { $this->setError($exception->getMessage()); return false; } } /** * Method to save the form data. * * @param array $data The form data. * * @return boolean True on success, False on error. * * @since 3.9.0 */ public function save($data) { $table = $this->getTable(); $key = $table->getKeyName(); $pk = !empty($data[$key]) ? $data[$key] : (int) $this->getState($this->getName() . '.id'); if (!$pk && !JFactory::getConfig()->get('mailonline', 1)) { $this->setError(JText::_('COM_PRIVACY_ERROR_CANNOT_CREATE_REQUEST_WHEN_SENDMAIL_DISABLED')); return false; } return parent::save($data); } /** * Method to validate the form data. * * @param JForm $form The form to validate against. * @param array $data The data to validate. * @param string $group The name of the field group to validate. * * @return array|boolean Array of filtered data if valid, false otherwise. * * @see JFormRule * @see JFilterInput * @since 3.9.0 */ public function validate($form, $data, $group = null) { $validatedData = parent::validate($form, $data, $group); // If parent validation failed there's no point in doing our extended validation if ($validatedData === false) { return false; } // Make sure the status is always 0 $validatedData['status'] = 0; // The user cannot create a request for their own account if (strtolower(JFactory::getUser()->email) === strtolower($validatedData['email'])) { $this->setError(JText::_('COM_PRIVACY_ERROR_CANNOT_CREATE_REQUEST_FOR_SELF')); return false; } // Check for an active request for this email address $db = $this->getDbo(); $query = $db->getQuery(true) ->select('COUNT(id)') ->from('#__privacy_requests') ->where('email = ' . $db->quote($validatedData['email'])) ->where('request_type = ' . $db->quote($validatedData['request_type'])) ->where('status IN (0, 1)'); $activeRequestCount = (int) $db->setQuery($query)->loadResult(); if ($activeRequestCount > 0) { $this->setError(JText::_('COM_PRIVACY_ERROR_ACTIVE_REQUEST_FOR_EMAIL')); return false; } return $validatedData; } } models/requests.php000064400000011202152325744620010421 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\CMS\Component\ComponentHelper; /** * Requests management model class. * * @since 3.9.0 */ class PrivacyModelRequests extends JModelList { /** * Constructor. * * @param array $config An optional associative array of configuration settings. * * @since 3.9.0 */ public function __construct($config = array()) { if (empty($config['filter_fields'])) { $config['filter_fields'] = array( 'id', 'a.id', 'email', 'a.email', 'requested_at', 'a.requested_at', 'request_type', 'a.request_type', 'status', 'a.status', ); } parent::__construct($config); } /** * Method to get a JDatabaseQuery object for retrieving the data set from a database. * * @return JDatabaseQuery * * @since 3.9.0 */ protected function getListQuery() { // Create a new query object. $db = $this->getDbo(); $query = $db->getQuery(true); // Select the required fields from the table. $query->select($this->getState('list.select', 'a.*')); $query->from($db->quoteName('#__privacy_requests', 'a')); // Filter by status $status = $this->getState('filter.status'); if (is_numeric($status)) { $query->where('a.status = ' . (int) $status); } // Filter by request type $requestType = $this->getState('filter.request_type', ''); if ($requestType) { $query->where('a.request_type = ' . $db->quote($db->escape($requestType, true))); } // Filter by search in email $search = $this->getState('filter.search'); if (!empty($search)) { if (stripos($search, 'id:') === 0) { $query->where($db->quoteName('a.id') . ' = ' . (int) substr($search, 3)); } else { $search = $db->quote('%' . $db->escape($search, true) . '%'); $query->where('(' . $db->quoteName('a.email') . ' LIKE ' . $search . ')'); } } // Handle the list ordering. $ordering = $this->getState('list.ordering'); $direction = $this->getState('list.direction'); if (!empty($ordering)) { $query->order($db->escape($ordering) . ' ' . $db->escape($direction)); } return $query; } /** * 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 * * @since 3.9.0 */ protected function getStoreId($id = '') { // Compile the store id. $id .= ':' . $this->getState('filter.search'); $id .= ':' . $this->getState('filter.status'); $id .= ':' . $this->getState('filter.request_type'); return parent::getStoreId($id); } /** * Method to auto-populate the model state. * * Note. Calling getState in this method will result in recursion. * * @param string $ordering An optional ordering field. * @param string $direction An optional direction (asc|desc). * * @return void * * @since 3.9.0 */ protected function populateState($ordering = 'a.id', $direction = 'desc') { // Load the filter state. $this->setState( 'filter.search', $this->getUserStateFromRequest($this->context . '.filter.search', 'filter_search') ); $this->setState( 'filter.status', $this->getUserStateFromRequest($this->context . '.filter.status', 'filter_status', '', 'int') ); $this->setState( 'filter.request_type', $this->getUserStateFromRequest($this->context . '.filter.request_type', 'filter_request_type', '', 'string') ); // Load the parameters. $this->setState('params', JComponentHelper::getParams('com_privacy')); // List state information. parent::populateState($ordering, $direction); } /** * Method to return number privacy requests older than X days. * * @return integer * * @since 3.9.0 */ public function getNumberUrgentRequests() { // Load the parameters. $params = ComponentHelper::getComponent('com_privacy')->getParams(); $notify = (int) $params->get('notify', 14); $now = JFactory::getDate()->toSql(); $period = '-' . $notify; $db = $this->getDbo(); $query = $db->getQuery(true) ->select('COUNT(*)'); $query->from($db->quoteName('#__privacy_requests')); $query->where($db->quoteName('status') . ' = 1 '); $query->where($query->dateAdd($db->quote($now), $period, 'DAY') . ' > ' . $db->quoteName('requested_at')); $db->setQuery($query); return (int) $db->loadResult(); } } tables/consent.php000064400000002775152325744620010225 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Table interface class for the #__privacy_consents table * * @property integer $id Item ID (primary key) * @property integer $remind The status of the reminder request * @property string $token Hashed token for the reminder request * @property integer $user_id User ID (pseudo foreign key to the #__users table) if the request is associated to a user account * * @since 3.9.0 */ class PrivacyTableConsent extends JTable { /** * The class constructor. * * @param JDatabaseDriver $db JDatabaseDriver connector object. * * @since 3.9.0 */ public function __construct(JDatabaseDriver $db) { parent::__construct('#__privacy_consents', 'id', $db); } /** * Method to store a row in the database from the Table instance properties. * * @param boolean $updateNulls True to update fields even if they are null. * * @return boolean True on success. * * @since 3.9.0 */ public function store($updateNulls = false) { $date = JFactory::getDate(); // Set default values for new records if (!$this->id) { if (!$this->remind) { $this->remind = '0'; } if (!$this->created) { $this->created = $date->toSql(); } } return parent::store($updateNulls); } } tables/request.php000064400000003475152325744620010242 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Table interface class for the #__privacy_requests table * * @property integer $id Item ID (primary key) * @property string $email The email address of the individual requesting the data * @property string $requested_at The time the request was created at * @property integer $status The status of the information request * @property string $request_type The type of information request * @property string $confirm_token Hashed token for confirming the information request * @property string $confirm_token_created_at The time the confirmation token was generated * * @since 3.9.0 */ class PrivacyTableRequest extends JTable { /** * The class constructor. * * @param JDatabaseDriver $db JDatabaseDriver connector object. * * @since 3.9.0 */ public function __construct(JDatabaseDriver $db) { parent::__construct('#__privacy_requests', 'id', $db); } /** * Method to store a row in the database from the Table instance properties. * * @param boolean $updateNulls True to update fields even if they are null. * * @return boolean True on success. * * @since 3.9.0 */ public function store($updateNulls = false) { $date = JFactory::getDate(); // Set default values for new records if (!$this->id) { if (!$this->status) { $this->status = '0'; } if (!$this->requested_at) { $this->requested_at = $date->toSql(); } } return parent::store($updateNulls); } } views/capabilities/tmpl/default.php000064400000003346152325744620013463 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** @var PrivacyViewCapabilities $this */ ?> <?php if (!empty($this->sidebar)) : ?> <div id="j-sidebar-container" class="span2"> <?php echo $this->sidebar; ?> </div> <div id="j-main-container" class="span10"> <?php else : ?> <div id="j-main-container"> <?php endif; ?> <div class="alert alert-info"> <h4 class="alert-heading"><?php echo JText::_('COM_PRIVACY_MSG_CAPABILITIES_ABOUT_THIS_INFORMATION'); ?></h4> <?php echo JText::_('COM_PRIVACY_MSG_CAPABILITIES_INTRODUCTION'); ?> </div> <?php if (empty($this->capabilities)) : ?> <div class="alert alert-no-items"> <?php echo JText::_('COM_PRIVACY_MSG_CAPABILITIES_NO_CAPABILITIES'); ?> </div> <?php else : ?> <?php $i = 0; ?> <?php echo JHtml::_('bootstrap.startAccordion', 'slide-capabilities', array('active' => 'slide-0')); ?> <?php foreach ($this->capabilities as $extension => $capabilities) : ?> <?php echo JHtml::_('bootstrap.addSlide', 'slide-capabilities', $extension, 'slide-' . $i); ?> <?php if (empty($capabilities)) : ?> <div class="alert alert-no-items"> <?php echo JText::_('COM_PRIVACY_MSG_EXTENSION_NO_CAPABILITIES'); ?> </div> <?php else : ?> <ul> <?php foreach ($capabilities as $capability) : ?> <li><?php echo $capability; ?></li> <?php endforeach; ?> </ul> <?php endif; ?> <?php echo JHtml::_('bootstrap.endSlide'); ?> <?php $i++; ?> <?php endforeach; ?> <?php echo JHtml::_('bootstrap.endAccordion'); ?> <?php endif; ?> </div> views/capabilities/view.html.php000064400000003331152325744620012772 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Capabilities view class * * @since 3.9.0 */ class PrivacyViewCapabilities extends JViewLegacy { /** * The reported extension capabilities * * @var array * @since 3.9.0 */ protected $capabilities; /** * The HTML markup for the sidebar * * @var string * @since 3.9.0 */ protected $sidebar; /** * The state information * * @var JObject * @since 3.9.0 */ protected $state; /** * Execute and display a template script. * * @param string $tpl The name of the template file to parse; automatically searches through the template paths. * * @return mixed A string if successful, otherwise an Error object. * * @see JViewLegacy::loadTemplate() * @since 3.9.0 * @throws Exception */ public function display($tpl = null) { // Initialise variables $this->capabilities = $this->get('Capabilities'); $this->state = $this->get('State'); // Check for errors. if (count($errors = $this->get('Errors'))) { throw new Exception(implode("\n", $errors), 500); } $this->addToolbar(); $this->sidebar = JHtmlSidebar::render(); return parent::display($tpl); } /** * Add the page title and toolbar. * * @return void * * @since 3.9.0 */ protected function addToolbar() { JToolbarHelper::title(JText::_('COM_PRIVACY_VIEW_CAPABILITIES'), 'lock'); JToolbarHelper::preferences('com_privacy'); JToolbarHelper::help('JHELP_COMPONENTS_PRIVACY_CAPABILITIES'); } } views/consents/tmpl/default.php000064400000010172152325744620012661 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** @var PrivacyViewConsent $this */ // Load the tooltip behavior. JHtml::_('bootstrap.tooltip'); JHtml::_('behavior.multiselect'); JHtml::_('formbehavior.chosen', 'select'); $user = JFactory::getUser(); $listOrder = $this->escape($this->state->get('list.ordering')); $listDirn = $this->escape($this->state->get('list.direction')); $now = JFactory::getDate(); $stateIcons = array(-1 => 'trash', 0 => 'archive', 1 => 'publish'); $stateMsgs = array(-1 => JText::_('COM_PRIVACY_CONSENTS_STATE_INVALIDATED'), 0 => JText::_('COM_PRIVACY_CONSENTS_STATE_OBSOLETE'), 1 => JText::_('COM_PRIVACY_CONSENTS_STATE_VALID')); ?> <form action="<?php echo JRoute::_('index.php?option=com_privacy&view=consents'); ?>" method="post" name="adminForm" id="adminForm"> <?php if (!empty($this->sidebar)) : ?> <div id="j-sidebar-container" class="span2"> <?php echo $this->sidebar; ?> </div> <div id="j-main-container" class="span10"> <?php else : ?> <div id="j-main-container"> <?php endif; ?> <?php echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this)); ?> <div class="clearfix"> </div> <?php if (empty($this->items)) : ?> <div class="alert alert-no-items"> <?php echo JText::_('COM_PRIVACY_MSG_CONSENTS_NO_CONSENTS'); ?> </div> <?php else : ?> <table class="table table-striped" id="consentList"> <thead> <tr> <th width="1%" class="center"> <?php echo JHtml::_('grid.checkall'); ?> </th> <th width="1%" class="nowrap center"> <?php echo JHtml::_('searchtools.sort', 'JSTATUS', 'a.state', $listDirn, $listOrder); ?> </th> <th width="10%" class="nowrap"> <?php echo JHtml::_('searchtools.sort', 'JGLOBAL_USERNAME', 'u.username', $listDirn, $listOrder); ?> </th> <th width="1%" class="nowrap"> <?php echo JHtml::_('searchtools.sort', 'COM_PRIVACY_HEADING_USERID', 'a.user_id', $listDirn, $listOrder); ?> </th> <th width="10%" class="nowrap"> <?php echo JHtml::_('searchtools.sort', 'COM_PRIVACY_HEADING_CONSENTS_SUBJECT', 'a.subject', $listDirn, $listOrder); ?> </th> <th class="nowrap"> <?php echo JText::_('COM_PRIVACY_HEADING_CONSENTS_BODY'); ?> </th> <th width="15%" class="nowrap"> <?php echo JHtml::_('searchtools.sort', 'COM_PRIVACY_HEADING_CONSENTS_CREATED', 'a.created', $listDirn, $listOrder); ?> </th> <th width="1%" class="nowrap hidden-phone"> <?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder); ?> </th> </tr> </thead> <tfoot> <tr> <td colspan="9"> <?php echo $this->pagination->getListFooter(); ?> </td> </tr> </tfoot> <tbody> <?php foreach ($this->items as $i => $item) : ?> <tr class="row<?php echo $i % 2; ?>"> <td class="center"> <?php echo JHtml::_('grid.id', $i, $item->id); ?> </td> <td> <span class="icon icon-<?php echo $stateIcons[$item->state]; ?>" title="<?php echo $stateMsgs[$item->state]; ?>"></span> </td> <td> <?php echo $item->username; ?> </td> <td> <?php echo $item->user_id; ?> </td> <td> <?php echo JText::_($item->subject); ?> </td> <td> <?php echo $item->body; ?> </td> <td class="break-word"> <span class="hasTooltip" title="<?php echo JHtml::_('date', $item->created, JText::_('DATE_FORMAT_LC6')); ?>"> <?php echo JHtml::_('date.relative', new JDate($item->created), null, $now); ?> </span> </td> <td class="hidden-phone"> <?php echo (int) $item->id; ?> </td> </tr> <?php endforeach; ?> </tbody> </table> <?php endif; ?> <input type="hidden" name="task" value="" /> <input type="hidden" name="boxchecked" value="0" /> <?php echo JHtml::_('form.token'); ?> </div> </form> views/consents/tmpl/default.xml000064400000000322152325744620012666 0ustar00<?xml version="1.0" encoding="utf-8"?> <metadata> <layout title="COM_PRIVACY_CONSENTS_VIEW_DEFAULT_TITLE"> <message> <![CDATA[COM_PRIVACY_CONSENTS_VIEW_DEFAULT_DESC]]> </message> </layout> </metadata> views/consents/view.html.php000064400000005661152325744620012205 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Consents view class * * @since 3.9.0 */ class PrivacyViewConsents extends JViewLegacy { /** * The active search tools filters * * @var array * @since 3.9.0 * @note Must be public to be accessed from the search tools layout */ public $activeFilters; /** * Form instance containing the search tools filter form * * @var JForm * @since 3.9.0 * @note Must be public to be accessed from the search tools layout */ public $filterForm; /** * The items to display * * @var array * @since 3.9.0 */ protected $items; /** * The pagination object * * @var JPagination * @since 3.9.0 */ protected $pagination; /** * The HTML markup for the sidebar * * @var string * @since 3.9.0 */ protected $sidebar; /** * The state information * * @var JObject * @since 3.9.0 */ protected $state; /** * Execute and display a template script. * * @param string $tpl The name of the template file to parse; automatically searches through the template paths. * * @return mixed A string if successful, otherwise an Error object. * * @see JViewLegacy::loadTemplate() * @since 3.9.0 * @throws Exception */ public function display($tpl = null) { // Initialise variables $this->items = $this->get('Items'); $this->pagination = $this->get('Pagination'); $this->state = $this->get('State'); $this->filterForm = $this->get('FilterForm'); $this->activeFilters = $this->get('ActiveFilters'); // Check for errors. if (count($errors = $this->get('Errors'))) { throw new Exception(implode("\n", $errors), 500); } $this->addToolbar(); $this->sidebar = JHtmlSidebar::render(); return parent::display($tpl); } /** * Add the page title and toolbar. * * @return void * * @since 3.9.0 */ protected function addToolbar() { JToolbarHelper::title(JText::_('COM_PRIVACY_VIEW_CONSENTS'), 'lock'); $bar = JToolbar::getInstance('toolbar'); // Add a button to invalidate a consent $bar->appendButton( 'Confirm', 'COM_PRIVACY_CONSENTS_TOOLBAR_INVALIDATE_CONFIRM_MSG', 'trash', 'COM_PRIVACY_CONSENTS_TOOLBAR_INVALIDATE', 'consents.invalidate', true ); // If the filter is restricted to a specific subject, show the "Invalidate all" button if ($this->state->get('filter.subject') != '') { $bar->appendButton( 'Confirm', 'COM_PRIVACY_CONSENTS_TOOLBAR_INVALIDATE_ALL_CONFIRM_MSG', 'cancel', 'COM_PRIVACY_CONSENTS_TOOLBAR_INVALIDATE_ALL', 'consents.invalidateAll', false ); } JToolbarHelper::preferences('com_privacy'); JToolbarHelper::help('JHELP_COMPONENTS_PRIVACY_CONSENTS'); } } views/dashboard/tmpl/default.php000064400000020115152325744620012752 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\CMS\Language\Text; use Joomla\CMS\Router\Route; /** @var PrivacyViewDashboard $this */ // Include the component HTML helpers. JHtml::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/html'); JHtml::_('bootstrap.tooltip'); $totalRequests = 0; $activeRequests = 0; ?> <?php if (!empty($this->sidebar)) : ?> <div id="j-sidebar-container" class="span2"> <?php echo $this->sidebar; ?> </div> <div id="j-main-container" class="span10"> <?php else : ?> <div id="j-main-container"> <?php endif; ?> <div class="row-fluid"> <div class="span6"> <div class="well well-small"> <h3 class="module-title nav-header"><?php echo Text::_('COM_PRIVACY_DASHBOARD_HEADING_TOTAL_REQUEST_COUNT'); ?></h3> <div class="row-striped"> <?php if (count($this->requestCounts)) : ?> <div class="row-fluid"> <div class="span5"><strong><?php echo Text::_('COM_PRIVACY_DASHBOARD_HEADING_REQUEST_TYPE'); ?></strong></div> <div class="span5"><strong><?php echo Text::_('COM_PRIVACY_DASHBOARD_HEADING_REQUEST_STATUS'); ?></strong></div> <div class="span2"><strong><?php echo Text::_('COM_PRIVACY_DASHBOARD_HEADING_REQUEST_COUNT'); ?></strong></div> </div> <?php foreach ($this->requestCounts as $row) : ?> <div class="row-fluid"> <div class="span5"> <a class="hasTooltip" href="<?php echo JRoute::_('index.php?option=com_privacy&view=requests&filter[request_type]=' . $row->request_type . '&filter[status]=' . $row->status); ?>" data-original-title="<?php echo JText::_('COM_PRIVACY_DASHBOARD_VIEW_REQUESTS'); ?>"> <strong><?php echo Text::_('COM_PRIVACY_HEADING_REQUEST_TYPE_TYPE_' . $row->request_type); ?></strong> </a> </div> <div class="span5"><?php echo JHtml::_('PrivacyHtml.helper.statusLabel', $row->status); ?></div> <div class="span2"><span class="badge badge-info"><?php echo $row->count; ?></span></div> </div> <?php if (in_array($row->status, array(0, 1))) : ?> <?php $activeRequests += $row->count; ?> <?php endif; ?> <?php $totalRequests += $row->count; ?> <?php endforeach; ?> <div class="row-fluid"> <div class="span5"><?php echo Text::plural('COM_PRIVACY_DASHBOARD_BADGE_TOTAL_REQUESTS', $totalRequests); ?></div> <div class="span7"><?php echo Text::plural('COM_PRIVACY_DASHBOARD_BADGE_ACTIVE_REQUESTS', $activeRequests); ?></div> </div> <?php else : ?> <div class="row-fluid"> <div class="span12"> <div class="alert"><?php echo Text::_('COM_PRIVACY_DASHBOARD_NO_REQUESTS'); ?></div> </div> </div> <?php endif; ?> </div> </div> </div> <div class="span6"> <div class="well well-small"> <h3 class="module-title nav-header"><?php echo Text::_('COM_PRIVACY_DASHBOARD_HEADING_STATUS_CHECK'); ?></h3> <div class="row-striped"> <div class="row-fluid"> <div class="span3"><strong><?php echo Text::_('COM_PRIVACY_DASHBOARD_HEADING_STATUS'); ?></strong></div> <div class="span9"><strong><?php echo Text::_('COM_PRIVACY_DASHBOARD_HEADING_CHECK'); ?></strong></div> </div> <div class="row-fluid"> <div class="span3"> <?php if ($this->privacyPolicyInfo['published'] && $this->privacyPolicyInfo['articlePublished']) : ?> <span class="label label-success"> <span class="icon-checkbox" aria-hidden="true"></span> <?php echo Text::_('JPUBLISHED'); ?> </span> <?php elseif ($this->privacyPolicyInfo['published'] && !$this->privacyPolicyInfo['articlePublished']) : ?> <span class="label label-warning"> <span class="icon-warning" aria-hidden="true"></span> <?php echo Text::_('JUNPUBLISHED'); ?> </span> <?php else : ?> <span class="label label-warning"> <span class="icon-warning" aria-hidden="true"></span> <?php echo Text::_('COM_PRIVACY_STATUS_CHECK_NOT_AVAILABLE'); ?> </span> <?php endif; ?> </div> <div class="span9"> <div><?php echo Text::_('COM_PRIVACY_STATUS_CHECK_PRIVACY_POLICY_PUBLISHED'); ?></div> <?php if ($this->privacyPolicyInfo['editLink'] !== '') : ?> <small><a href="<?php echo $this->privacyPolicyInfo['editLink']; ?>"><?php echo Text::_('COM_PRIVACY_EDIT_PRIVACY_POLICY'); ?></a></small> <?php else : ?> <?php $link = Route::_('index.php?option=com_plugins&task=plugin.edit&extension_id=' . $this->privacyConsentPluginId); ?> <small><a href="<?php echo $link; ?>"><?php echo Text::_('COM_PRIVACY_EDIT_PRIVACY_CONSENT_PLUGIN'); ?></a></small> <?php endif; ?> </div> </div> <div class="row-fluid"> <div class="span3"> <?php if ($this->requestFormPublished['published'] && $this->requestFormPublished['exists']) : ?> <span class="label label-success"> <span class="icon-checkbox" aria-hidden="true"></span> <?php echo Text::_('JPUBLISHED'); ?> </span> <?php elseif (!$this->requestFormPublished['published'] && $this->requestFormPublished['exists']) : ?> <span class="label label-warning"> <span class="icon-warning" aria-hidden="true"></span> <?php echo Text::_('JUNPUBLISHED'); ?> </span> <?php else : ?> <span class="label label-warning"> <span class="icon-warning" aria-hidden="true"></span> <?php echo Text::_('COM_PRIVACY_STATUS_CHECK_NOT_AVAILABLE'); ?> </span> <?php endif; ?> </div> <div class="span9"> <div><?php echo Text::_('COM_PRIVACY_STATUS_CHECK_REQUEST_FORM_MENU_ITEM_PUBLISHED'); ?></div> <?php if ($this->requestFormPublished['link'] !== '') : ?> <small><a href="<?php echo $this->requestFormPublished['link']; ?>"><?php echo $this->requestFormPublished['link']; ?></a></small> <?php endif; ?> </div> </div> <div class="row-fluid"> <div class="span3"> <?php if ($this->numberOfUrgentRequests === 0) : ?> <span class="label label-success"> <span class="icon-checkbox" aria-hidden="true"></span> <?php echo Text::_('JNONE'); ?> </span> <?php else : ?> <span class="label label-important"> <span class="icon-warning" aria-hidden="true"></span> <?php echo Text::_('WARNING'); ?> </span> <?php endif; ?> </div> <div class="span9"> <div><?php echo Text::_('COM_PRIVACY_STATUS_CHECK_OUTSTANDING_URGENT_REQUESTS'); ?></div> <small><?php echo Text::plural('COM_PRIVACY_STATUS_CHECK_OUTSTANDING_URGENT_REQUESTS_DESCRIPTION', $this->urgentRequestDays); ?></small> <?php if ($this->numberOfUrgentRequests > 0) : ?> <small><a href="<?php echo Route::_('index.php?option=com_privacy&view=requests&filter[status]=1&list[fullordering]=a.requested_at ASC'); ?>"><?php echo JText::_('COM_PRIVACY_SHOW_URGENT_REQUESTS'); ?></a></small> <?php endif; ?> </div> </div> <div class="row-fluid"> <div class="span3"> <?php if ($this->sendMailEnabled) : ?> <span class="label label-success"> <span class="icon-checkbox" aria-hidden="true"></span> <?php echo Text::_('JENABLED'); ?> </span> <?php else : ?> <span class="label label-important"> <span class="icon-warning" aria-hidden="true"></span> <?php echo Text::_('JDISABLED'); ?> </span> <?php endif; ?> </div> <div class="span9"> <?php if (!$this->sendMailEnabled) : ?> <div><?php echo Text::_('COM_PRIVACY_STATUS_CHECK_SENDMAIL_DISABLED'); ?></div> <small><?php echo Text::_('COM_PRIVACY_STATUS_CHECK_SENDMAIL_DISABLED_DESCRIPTION'); ?></small> <?php else : ?> <div><?php echo Text::_('COM_PRIVACY_STATUS_CHECK_SENDMAIL_ENABLED'); ?></div> <?php endif; ?> </div> </div> </div> </div> </div> </div> </div> views/dashboard/tmpl/default.xml000064400000000324152325744620012763 0ustar00<?xml version="1.0" encoding="utf-8"?> <metadata> <layout title="COM_PRIVACY_DASHBOARD_VIEW_DEFAULT_TITLE"> <message> <![CDATA[COM_PRIVACY_DASHBOARD_VIEW_DEFAULT_DESC]]> </message> </layout> </metadata> views/dashboard/view.html.php000064400000005656152325744620012304 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\CMS\Component\ComponentHelper; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; /** * Dashboard view class * * @since 3.9.0 */ class PrivacyViewDashboard extends JViewLegacy { /** * Number of urgent requests based on the component configuration * * @var integer * @since 3.9.0 */ protected $numberOfUrgentRequests; /** * Information about whether a privacy policy is published * * @var array * @since 3.9.0 */ protected $privacyPolicyInfo; /** * The request counts * * @var array * @since 3.9.0 */ protected $requestCounts; /** * Information about whether a menu item for the request form is published * * @var array * @since 3.9.0 */ protected $requestFormPublished; /** * Flag indicating the site supports sending email * * @var boolean * @since 3.9.0 */ protected $sendMailEnabled; /** * The HTML markup for the sidebar * * @var string * @since 3.9.0 */ protected $sidebar; /** * Id of the system privacy consent plugin * * @var integer * @since 3.9.2 */ protected $privacyConsentPluginId; /** * Execute and display a template script. * * @param string $tpl The name of the template file to parse; automatically searches through the template paths. * * @return mixed A string if successful, otherwise an Error object. * * @see JViewLegacy::loadTemplate() * @since 3.9.0 * @throws Exception */ public function display($tpl = null) { // Initialise variables $this->privacyConsentPluginId = PrivacyHelper::getPrivacyConsentPluginId(); $this->privacyPolicyInfo = $this->get('PrivacyPolicyInfo'); $this->requestCounts = $this->get('RequestCounts'); $this->requestFormPublished = $this->get('RequestFormPublished'); $this->sendMailEnabled = (bool) Factory::getConfig()->get('mailonline', 1); /** @var PrivacyModelRequests $requestsModel */ $requestsModel = $this->getModel('requests'); $this->numberOfUrgentRequests = $requestsModel->getNumberUrgentRequests(); // Check for errors. if (count($errors = $this->get('Errors'))) { throw new Exception(implode("\n", $errors), 500); } $this->urgentRequestDays = (int) ComponentHelper::getParams('com_privacy')->get('notify', 14); $this->addToolbar(); $this->sidebar = JHtmlSidebar::render(); return parent::display($tpl); } /** * Add the page title and toolbar. * * @return void * * @since 3.9.0 */ protected function addToolbar() { JToolbarHelper::title(Text::_('COM_PRIVACY_VIEW_DASHBOARD'), 'lock'); JToolbarHelper::preferences('com_privacy'); JToolbarHelper::help('JHELP_COMPONENTS_PRIVACY_DASHBOARD'); } } views/export/view.xml.php000064400000002640152325744620011520 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; JLoader::register('PrivacyHelper', JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/privacy.php'); /** * Export view class * * @since 3.9.0 * * @property-read \Joomla\CMS\Document\XmlDocument $document */ class PrivacyViewExport extends JViewLegacy { /** * Execute and display a template script. * * @param string $tpl The name of the template file to parse; automatically searches through the template paths. * * @return mixed A string if successful, otherwise an Error object. * * @see JViewLegacy::loadTemplate() * @since 3.9.0 * @throws Exception */ public function display($tpl = null) { /** @var PrivacyModelExport $model */ $model = $this->getModel(); $exportData = $model->collectDataForExportRequest(); // Check for errors. if (count($errors = $this->get('Errors'))) { throw new Exception(implode("\n", $errors), 500); } $requestId = $model->getState($model->getName() . '.request_id'); // This document should always be downloaded $this->document->setDownload(true); $this->document->setName('export-request-' . $requestId); echo PrivacyHelper::renderDataAsXml($exportData); } } views/request/tmpl/default.php000064400000005554152325744620012525 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** @var PrivacyViewRequest $this */ // Include the component HTML helpers. JHtml::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/html'); JHtml::_('behavior.formvalidator'); JHtml::_('behavior.keepalive'); $js = <<< JS Joomla.submitbutton = function(task) { if (task === 'request.cancel' || document.formvalidator.isValid(document.getElementById('item-form'))) { Joomla.submitform(task, document.getElementById('item-form')); } }; JS; JFactory::getDocument()->addScriptDeclaration($js); ?> <form action="<?php echo JRoute::_('index.php?option=com_privacy&view=request&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="item-form" class="form-validate"> <div class="row-fluid"> <div class="span4"> <h3><?php echo JText::_('COM_PRIVACY_HEADING_REQUEST_INFORMATION'); ?></h3> <dl class="dl-horizontal"> <dt><?php echo JText::_('JGLOBAL_EMAIL'); ?>:</dt> <dd><?php echo $this->item->email; ?></dd> <dt><?php echo JText::_('JSTATUS'); ?>:</dt> <dd><?php echo JHtml::_('PrivacyHtml.helper.statusLabel', $this->item->status); ?></dd> <dt><?php echo JText::_('COM_PRIVACY_FIELD_REQUEST_TYPE_LABEL'); ?>:</dt> <dd><?php echo JText::_('COM_PRIVACY_HEADING_REQUEST_TYPE_TYPE_' . $this->item->request_type); ?></dd> <dt><?php echo JText::_('COM_PRIVACY_FIELD_REQUESTED_AT_LABEL'); ?>:</dt> <dd><?php echo JHtml::_('date', $this->item->requested_at, JText::_('DATE_FORMAT_LC6')); ?></dd> </dl> </div> <div class="span8"> <h3><?php echo JText::_('COM_PRIVACY_HEADING_ACTION_LOG'); ?></h3> <?php if (empty($this->actionlogs)) : ?> <div class="alert alert-no-items"> <?php echo JText::_('JGLOBAL_NO_MATCHING_RESULTS'); ?> </div> <?php else : ?> <table class="table table-striped table-hover"> <thead> <th> <?php echo JText::_('COM_ACTIONLOGS_ACTION'); ?> </th> <th> <?php echo JText::_('COM_ACTIONLOGS_DATE'); ?> </th> <th> <?php echo JText::_('COM_ACTIONLOGS_NAME'); ?> </th> </thead> <tbody> <?php foreach ($this->actionlogs as $i => $item) : ?> <tr class="row<?php echo $i % 2; ?>"> <td> <?php echo ActionlogsHelper::getHumanReadableLogMessage($item); ?> </td> <td> <?php echo JHtml::_('date', $item->log_date, JText::_('DATE_FORMAT_LC6')); ?> </td> <td> <?php echo $item->name; ?> </td> </tr> <?php endforeach; ?> </tbody> </table> <?php endif;?> </div> </div> <input type="hidden" name="task" value="" /> <?php echo JHtml::_('form.token'); ?> </form> views/request/tmpl/edit.php000064400000002451152325744620012017 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** @var PrivacyViewRequest $this */ JHtml::_('behavior.formvalidator'); JHtml::_('behavior.keepalive'); JHtml::_('formbehavior.chosen', 'select'); $js = <<< JS Joomla.submitbutton = function(task) { if (task === 'request.cancel' || document.formvalidator.isValid(document.getElementById('item-form'))) { Joomla.submitform(task, document.getElementById('item-form')); } }; JS; JFactory::getDocument()->addScriptDeclaration($js); ?> <form action="<?php echo JRoute::_('index.php?option=com_privacy&view=request&layout=edit&id=' . (int) $this->item->id); ?>" method="post" name="adminForm" id="item-form" class="form-validate"> <div class="form-horizontal"> <div class="row-fluid"> <div class="span9"> <fieldset class="adminform"> <?php echo $this->form->renderField('email'); ?> <?php echo $this->form->renderField('status'); ?> <?php echo $this->form->renderField('request_type'); ?> </fieldset> </div> </div> <input type="hidden" name="task" value="" /> <?php echo JHtml::_('form.token'); ?> </div> </form> views/request/view.html.php000064400000010534152325744620012034 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Request view class * * @since 3.9.0 */ class PrivacyViewRequest extends JViewLegacy { /** * The action logs for the item * * @var array * @since 3.9.0 */ protected $actionlogs; /** * The form object * * @var JForm * @since 3.9.0 */ protected $form; /** * The item record * * @var JObject * @since 3.9.0 */ protected $item; /** * The state information * * @var JObject * @since 3.9.0 */ protected $state; /** * Execute and display a template script. * * @param string $tpl The name of the template file to parse; automatically searches through the template paths. * * @return mixed A string if successful, otherwise an Error object. * * @see JViewLegacy::loadTemplate() * @since 3.9.0 * @throws Exception */ public function display($tpl = null) { // Initialise variables. $this->item = $this->get('Item'); $this->state = $this->get('State'); // Variables only required for the default layout if ($this->getLayout() === 'default') { /** @var ActionlogsModelActionlogs $logsModel */ $logsModel = $this->getModel('actionlogs'); $this->actionlogs = $logsModel->getLogsForItem('com_privacy.request', $this->item->id); // Load the com_actionlogs language strings for use in the layout $lang = JFactory::getLanguage(); $lang->load('com_actionlogs', JPATH_ADMINISTRATOR, null, false, true) || $lang->load('com_actionlogs', JPATH_ADMINISTRATOR . '/components/com_actionlogs', null, false, true); } // Variables only required for the edit layout if ($this->getLayout() === 'edit') { $this->form = $this->get('Form'); } // Check for errors. if (count($errors = $this->get('Errors'))) { throw new Exception(implode("\n", $errors), 500); } $this->addToolbar(); return parent::display($tpl); } /** * Add the page title and toolbar. * * @return void * * @since 3.9.0 */ protected function addToolbar() { JFactory::getApplication('administrator')->set('hidemainmenu', true); // Set the title and toolbar based on the layout if ($this->getLayout() === 'edit') { JToolbarHelper::title(JText::_('COM_PRIVACY_VIEW_REQUEST_ADD_REQUEST'), 'lock'); JToolbarHelper::apply('request.save'); JToolbarHelper::cancel('request.cancel'); JToolbarHelper::help('JHELP_COMPONENTS_PRIVACY_REQUEST_EDIT'); } else { JToolbarHelper::title(JText::_('COM_PRIVACY_VIEW_REQUEST_SHOW_REQUEST'), 'lock'); $bar = JToolbar::getInstance('toolbar'); // Add transition and action buttons based on item status switch ($this->item->status) { case '0': $bar->appendButton('Standard', 'cancel-circle', 'COM_PRIVACY_TOOLBAR_INVALIDATE', 'request.invalidate', false); break; case '1': $return = '&return=' . base64_encode('index.php?option=com_privacy&view=request&id=' . (int) $this->item->id); $bar->appendButton('Standard', 'apply', 'COM_PRIVACY_TOOLBAR_COMPLETE', 'request.complete', false); $bar->appendButton('Standard', 'cancel-circle', 'COM_PRIVACY_TOOLBAR_INVALIDATE', 'request.invalidate', false); if ($this->item->request_type === 'export') { JToolbarHelper::link( JRoute::_('index.php?option=com_privacy&task=request.export&format=xml&id=' . (int) $this->item->id . $return), 'COM_PRIVACY_ACTION_EXPORT_DATA', 'download' ); if (JFactory::getConfig()->get('mailonline', 1)) { JToolbarHelper::link( JRoute::_( 'index.php?option=com_privacy&task=request.emailexport&id=' . (int) $this->item->id . $return . '&' . JSession::getFormToken() . '=1' ), 'COM_PRIVACY_ACTION_EMAIL_EXPORT_DATA', 'mail' ); } } if ($this->item->request_type === 'remove') { $bar->appendButton('Standard', 'delete', 'COM_PRIVACY_ACTION_DELETE_DATA', 'request.remove', false); } break; // Item is in a "locked" state and cannot transition default: break; } JToolbarHelper::cancel('request.cancel', 'JTOOLBAR_CLOSE'); JToolbarHelper::help('JHELP_COMPONENTS_PRIVACY_REQUEST'); } } } views/requests/tmpl/default.php000064400000013351152325744620012702 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** @var PrivacyViewRequests $this */ // Include the component HTML helpers. JHtml::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/html'); // Load the tooltip behavior. JHtml::_('bootstrap.tooltip'); JHtml::_('behavior.multiselect'); JHtml::_('formbehavior.chosen', 'select'); $user = JFactory::getUser(); $listOrder = $this->escape($this->state->get('list.ordering')); $listDirn = $this->escape($this->state->get('list.direction')); $now = JFactory::getDate(); $urgentRequestDate= clone $now; $urgentRequestDate->sub(new DateInterval('P' . $this->urgentRequestAge . 'D')); ?> <form action="<?php echo JRoute::_('index.php?option=com_privacy&view=requests'); ?>" method="post" name="adminForm" id="adminForm"> <?php if (!empty($this->sidebar)) : ?> <div id="j-sidebar-container" class="span2"> <?php echo $this->sidebar; ?> </div> <div id="j-main-container" class="span10"> <?php else : ?> <div id="j-main-container"> <?php endif; ?> <?php echo JLayoutHelper::render('joomla.searchtools.default', array('view' => $this)); ?> <div class="clearfix"> </div> <?php if (empty($this->items)) : ?> <div class="alert alert-no-items"> <?php echo JText::_('COM_PRIVACY_MSG_REQUESTS_NO_REQUESTS'); ?> </div> <?php else : ?> <table class="table table-striped" id="requestList"> <thead> <tr> <th width="5%" class="nowrap center"> <?php echo JText::_('COM_PRIVACY_HEADING_ACTIONS'); ?> </th> <th width="5%" class="nowrap center"> <?php echo JText::_('JSTATUS'); ?> </th> <th class="nowrap"> <?php echo JHtml::_('searchtools.sort', 'JGLOBAL_EMAIL', 'a.email', $listDirn, $listOrder); ?> </th> <th width="10%" class="nowrap"> <?php echo JHtml::_('searchtools.sort', 'COM_PRIVACY_HEADING_REQUEST_TYPE', 'a.request_type', $listDirn, $listOrder); ?> </th> <th width="20%" class="nowrap"> <?php echo JHtml::_('searchtools.sort', 'COM_PRIVACY_HEADING_REQUESTED_AT', 'a.requested_at', $listDirn, $listOrder); ?> </th> <th width="1%" class="nowrap hidden-phone"> <?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ID', 'a.id', $listDirn, $listOrder); ?> </th> </tr> </thead> <tfoot> <tr> <td colspan="7"> <?php echo $this->pagination->getListFooter(); ?> </td> </tr> </tfoot> <tbody> <?php foreach ($this->items as $i => $item) : ?> <?php $itemRequestedAt = new JDate($item->requested_at); ?> <tr class="row<?php echo $i % 2; ?>"> <td class="center"> <div class="btn-group"> <?php if ($item->status == 1 && $item->request_type === 'export') : ?> <a class="btn btn-micro hasTooltip" href="<?php echo JRoute::_('index.php?option=com_privacy&task=request.export&format=xml&id=' . (int) $item->id); ?>" title="<?php echo JText::_('COM_PRIVACY_ACTION_EXPORT_DATA'); ?>"><span class="icon-download" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('COM_PRIVACY_ACTION_EXPORT_DATA'); ?></span></a> <?php if ($this->sendMailEnabled) : ?> <a class="btn btn-micro hasTooltip" href="<?php echo JRoute::_('index.php?option=com_privacy&task=request.emailexport&id=' . (int) $item->id . '&' . JFactory::getSession()->getFormToken() . '=1'); ?>" title="<?php echo JText::_('COM_PRIVACY_ACTION_EMAIL_EXPORT_DATA'); ?>"><span class="icon-mail" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('COM_PRIVACY_ACTION_EMAIL_EXPORT_DATA'); ?></span></a> <?php endif; ?> <?php endif; ?> <?php if ($item->status == 1 && $item->request_type === 'remove') : ?> <a class="btn btn-micro hasTooltip" href="<?php echo JRoute::_('index.php?option=com_privacy&task=request.remove&id=' . (int) $item->id . '&' . JFactory::getSession()->getFormToken() . '=1'); ?>" title="<?php echo JText::_('COM_PRIVACY_ACTION_DELETE_DATA'); ?>"><span class="icon-delete" aria-hidden="true"></span><span class="element-invisible"><?php echo JText::_('COM_PRIVACY_ACTION_DELETE_DATA'); ?></span></a> <?php endif; ?> </div> </td> <td class="center"> <?php echo JHtml::_('PrivacyHtml.helper.statusLabel', $item->status); ?> </td> <td> <?php if ($item->status == 1 && $urgentRequestDate >= $itemRequestedAt) : ?> <span class="pull-right label label-important"><?php echo JText::_('COM_PRIVACY_BADGE_URGENT_REQUEST'); ?></span> <?php endif; ?> <a class="hasTooltip" href="<?php echo JRoute::_('index.php?option=com_privacy&view=request&id=' . (int) $item->id); ?>" title="<?php echo JText::_('COM_PRIVACY_ACTION_VIEW'); ?>"> <?php echo JStringPunycode::emailToUTF8($this->escape($item->email)); ?> </a> </td> <td class="break-word"> <?php echo JText::_('COM_PRIVACY_HEADING_REQUEST_TYPE_TYPE_' . $item->request_type); ?> </td> <td class="break-word"> <span class="hasTooltip" title="<?php echo JHtml::_('date', $item->requested_at, JText::_('DATE_FORMAT_LC6')); ?>"> <?php echo JHtml::_('date.relative', $itemRequestedAt, null, $now); ?> </span> </td> <td class="hidden-phone"> <?php echo (int) $item->id; ?> </td> </tr> <?php endforeach; ?> </tbody> </table> <?php endif; ?> <input type="hidden" name="task" value="" /> <input type="hidden" name="boxchecked" value="0" /> <?php echo JHtml::_('form.token'); ?> </div> </form> views/requests/tmpl/default.xml000064400000000322152325744620012705 0ustar00<?xml version="1.0" encoding="utf-8"?> <metadata> <layout title="COM_PRIVACY_REQUESTS_VIEW_DEFAULT_TITLE"> <message> <![CDATA[COM_PRIVACY_REQUESTS_VIEW_DEFAULT_DESC]]> </message> </layout> </metadata> views/requests/view.html.php000064400000005617152325744620012225 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Requests view class * * @since 3.9.0 */ class PrivacyViewRequests extends JViewLegacy { /** * The active search tools filters * * @var array * @since 3.9.0 * @note Must be public to be accessed from the search tools layout */ public $activeFilters; /** * Form instance containing the search tools filter form * * @var JForm * @since 3.9.0 * @note Must be public to be accessed from the search tools layout */ public $filterForm; /** * The items to display * * @var array * @since 3.9.0 */ protected $items; /** * The pagination object * * @var JPagination * @since 3.9.0 */ protected $pagination; /** * Flag indicating the site supports sending email * * @var boolean * @since 3.9.0 */ protected $sendMailEnabled; /** * The HTML markup for the sidebar * * @var string * @since 3.9.0 */ protected $sidebar; /** * The state information * * @var JObject * @since 3.9.0 */ protected $state; /** * The age of urgent requests * * @var integer * @since 3.9.0 */ protected $urgentRequestAge; /** * Execute and display a template script. * * @param string $tpl The name of the template file to parse; automatically searches through the template paths. * * @return mixed A string if successful, otherwise an Error object. * * @see JViewLegacy::loadTemplate() * @since 3.9.0 * @throws Exception */ public function display($tpl = null) { // Initialise variables $this->items = $this->get('Items'); $this->pagination = $this->get('Pagination'); $this->state = $this->get('State'); $this->filterForm = $this->get('FilterForm'); $this->activeFilters = $this->get('ActiveFilters'); $this->urgentRequestAge = (int) JComponentHelper::getParams('com_privacy')->get('notify', 14); $this->sendMailEnabled = (bool) JFactory::getConfig()->get('mailonline', 1); // Check for errors. if (count($errors = $this->get('Errors'))) { throw new Exception(implode("\n", $errors), 500); } $this->addToolbar(); $this->sidebar = JHtmlSidebar::render(); return parent::display($tpl); } /** * Add the page title and toolbar. * * @return void * * @since 3.9.0 */ protected function addToolbar() { JToolbarHelper::title(JText::_('COM_PRIVACY_VIEW_REQUESTS'), 'lock'); // Requests can only be created if mail sending is enabled if (JFactory::getConfig()->get('mailonline', 1)) { JToolbarHelper::addNew('request.add'); } JToolbarHelper::preferences('com_privacy'); JToolbarHelper::help('JHELP_COMPONENTS_PRIVACY_REQUESTS'); } } config.xml000064400000000547152325744620006553 0ustar00<?xml version="1.0" encoding="utf-8"?> <config> <fieldset name="privacy" label="COM_PRIVACY_OPTION_LABEL" > <field name="notify" type="integer" label="COM_PRIVACY_NOTIFY_LABEL" description="COM_PRIVACY_NOTIFY_DESC" first="1" last="29" step="1" default="14" filter="int" validate="number" /> </fieldset> </config> controller.php000064400000007453152325744620007463 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; use Joomla\CMS\Factory; use Joomla\CMS\Language\Text; use Joomla\CMS\Response\JsonResponse; use Joomla\CMS\Session\Session; /** * Privacy Controller * * @since 3.9.0 */ class PrivacyController extends JControllerLegacy { /** * The default view. * * @var string * @since 3.9.0 */ protected $default_view = 'dashboard'; /** * Method to display a view. * * @param boolean $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 $this * * @since 3.9.0 */ public function display($cachable = false, $urlparams = array()) { JLoader::register('PrivacyHelper', JPATH_ADMINISTRATOR . '/components/com_privacy/helpers/privacy.php'); // Get the document object. $document = JFactory::getDocument(); // Set the default view name and format from the Request. $vName = $this->input->get('view', $this->default_view); $vFormat = $document->getType(); $lName = $this->input->get('layout', 'default', 'string'); // Get and render the view. if ($view = $this->getView($vName, $vFormat)) { $model = $this->getModel($vName); $view->setModel($model, true); // For the dashboard view, we need to also push the requests model into the view if ($vName === 'dashboard') { $requestsModel = $this->getModel('Requests'); $view->setModel($requestsModel, false); } if ($vName === 'request') { // For the default layout, we need to also push the action logs model into the view if ($lName === 'default') { JLoader::register('ActionlogsHelper', JPATH_ADMINISTRATOR . '/components/com_actionlogs/helpers/actionlogs.php'); JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_actionlogs/models', 'ActionlogsModel'); $logsModel = $this->getModel('Actionlogs', 'ActionlogsModel'); // Set default ordering for the context $logsModel->setState('list.fullordering', 'a.log_date DESC'); // And push the model into the view $view->setModel($logsModel, false); } // For the edit layout, if mail sending is disabled then redirect back to the list view as the form is unusable in this state if ($lName === 'edit' && !JFactory::getConfig()->get('mailonline', 1)) { $this->setRedirect( JRoute::_('index.php?option=com_privacy&view=requests', false), JText::_('COM_PRIVACY_WARNING_CANNOT_CREATE_REQUEST_WHEN_SENDMAIL_DISABLED'), 'warning' ); return $this; } } $view->setLayout($lName); // Push document object into the view. $view->document = $document; // Load the submenu. PrivacyHelper::addSubmenu($this->input->get('view', $this->default_view)); $view->display(); } return $this; } /** * Fetch and report number urgent privacy requests in JSON format, for AJAX requests * * @return void * * @since 3.9.0 */ public function getNumberUrgentRequests() { $app = Factory::getApplication(); // Check for a valid token. If invalid, send a 403 with the error message. if (!Session::checkToken('get')) { $app->setHeader('status', 403, true); $app->sendHeaders(); echo new JsonResponse(new \Exception(Text::_('JINVALID_TOKEN'), 403)); $app->close(); } /** @var PrivacyModelRequests $model */ $model = $this->getModel('requests'); $numberUrgentRequests = $model->getNumberUrgentRequests(); echo new JResponseJson(array('number_urgent_requests' => $numberUrgentRequests)); $app->close(); } } privacy.php000064400000001112152325744620006737 0ustar00<?php /** * @package Joomla.Administrator * @subpackage com_privacy * * @copyright (C) 2018 Open Source Matters, Inc. <https://www.joomla.org> * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; // Only super user can access here if (!JFactory::getUser()->authorise('core.admin')) { throw new JAccessExceptionNotallowed(JText::_('JERROR_ALERTNOAUTHOR'), 403); } $controller = JControllerLegacy::getInstance('Privacy'); $controller->execute(JFactory::getApplication()->input->get('task')); $controller->redirect(); privacy.xml000064400000002512152325744620006755 0ustar00<?xml version="1.0" encoding="utf-8"?> <extension type="component" version="3.9" method="upgrade"> <name>com_privacy</name> <author>Joomla! Project</author> <creationDate>May 2018</creationDate> <copyright>(C) 2018 Open Source Matters, Inc.</copyright> <license>GNU General Public License version 2 or later; see LICENSE.txt</license> <authorEmail>admin@joomla.org</authorEmail> <authorUrl>www.joomla.org</authorUrl> <version>3.9.0</version> <description>COM_PRIVACY_XML_DESCRIPTION</description> <files folder="site"> <filename>controller.php</filename> <filename>privacy.php</filename> <filename>router.php</filename> <folder>controllers</folder> <folder>models</folder> <folder>views</folder> </files> <languages folder="site"> <language tag="en-GB">language/en-GB.com_privacy.ini</language> </languages> <administration> <files folder="admin"> <filename>config.xml</filename> <filename>controller.php</filename> <filename>privacy.php</filename> <folder>controllers</folder> <folder>helpers</folder> <folder>models</folder> <folder>tables</folder> <folder>views</folder> </files> <languages folder="admin"> <language tag="en-GB">language/en-GB.com_privacy.ini</language> <language tag="en-GB">language/en-GB.com_privacy.sys.ini</language> </languages> </administration> </extension>
/home/digilove/public_html/cache/./../41423/com_privacy.tar